Frendom
Frendom

Reputation: 558

Django Rest returning related items for each item

I was trying to find answer in similiar questions, but none was meeting my expectations.

I have 2 models:

class Artist(models.Model):
    name = models.CharField(max_length=255)
    music_type = models.CharField(max_lenght=50)

    def __str__(self):
        return self.name

class Event(models.Model):
    event_name = models.CharField(max_length=255)
    ...
    artists = models.ManyToManyField(Artist)

    def __str__(self):
        return self.event_name

I also have serializers.py file:

class EventSerializer(serializers.ModelSerializer):

    class Meta:
        model = Event
        fields = '__all__'


class ArtistSerializer(serializers.ModelSerializer):
    events = EventSerializer(source='event_set', many=True)

    class Meta:
        model = Artist
        fields ='__all__'

The event in ArtistSerializer allows me to return all events where artist takes part. Now for each artist I would like to get list of all artists if they ever were taking part in the same event.

For example I have 5 Artists (A1...A5) and 3 Events (E1...E3) In Event 1: [A1,A3]

In Event 2: [A3,A4,A5,A2]

In Event 3: [A2, A3]

So for A3 I would like to get list [A1,A4,A5,A2]
For A1: [A3]
For A2: [A3,A4,A5]

Unfortunately I have huge problem to create this query as SQL-query and ORM mechanism looks more complicated in this situation. Can somebody help me with this problem or give hints how to solve this?

If it's needed I'm gonna share more code

Upvotes: 0

Views: 36

Answers (1)

markwalker_
markwalker_

Reputation: 12859

You can query the through model to get the artists related to an event. This is the intermediate model which django will have created to make that M2M relationship.

Where you have a ManyToManyField it has an attribute of through which is the M2M model.

So from your event model you could do something like Event.artists.through.objects.all() and you'd see all the instances in your M2M model.

So to find out the artists which are linked to a given event you could query that same table;

Event.artists.through.objects.filter(event_id=1).select_related('artist')

This would then return all the objects in the M2M which belong to Event 1. You could then get the artists from there, or just grab the artist IDs Event.artists.through.objects.filter(event_id=1).values_list('artist_id, flat=True)

Given the scenario in your comment...

If you have an artist, then you can run a query to get the events they've been in, and then run another query with those event ids. In that second query you are then looking to get the artist ids that aren't the current artist you're already looking at.

# First get the events that the current artist has been in
event_ids = Event.artists.through.objects.filter(artist_id=1).values_list('event_id, flat=True)

# Then get the other artists who have been in the same events
other_artist_ids = Event.artists.through.objects.filter(event_id__in =event_ids).exclude(artist_id=1).values_list('artist_id, flat=True)

# or the full instances
other_artists = Event.artists.through.objects.filter(event_id__in =event_ids).exclude(artist_id=1).select_related('artist')

Upvotes: 1

Related Questions