0

My little podcast backend has some models, one of which is Episode. Now there are two new ones for guests (Guest) and topics (Topic) - both of which have a ManyToManyField to Episode. This basically works as intended in the admin. Now I need to bring that to the API.

The detailed Serializer/View for each episode already has some other related data (no many-to-many so far). I also checked this post but still can't get it it work and think I might miss something.

Here's the essence just for the guest example to keep it dense, topic is literally identical:

Episode Model:

class Episode(models.Model):
    number          = models.CharField(max_length=10, blank=False)
    title           = models.CharField(max_length=100, blank=False)
    show            = models.ForeignKey(Show, on_delete=models.PROTECT)
    created_at      = models.DateTimeField(auto_now=False)
    published_at    = models.DateTimeField(auto_now=False)
    updated_at      = models.DateTimeField(auto_now=False)
    cover_image     = models.URLField(null=True)

    def __str__(self):
        return self.title

Guest Model:

class Guest(models.Model):
    episodes        = models.ManyToManyField(Episode)
    name            = models.CharField(max_length=100, blank=False)
    twitter         = models.CharField(max_length=20, null=True)

    def __str__(self):
        return self.name

Serializer:

class GuestSerializer(serializers.ModelSerializer):
    class Meta:
        model = Guest
        fields = ('name',)

Episode Serializer where it should appear:

class EpisodeDetailSerializer(serializers.ModelSerializer):
    ...
    guest = GuestSerializer(many=True, read_only=True)
    topic = TopicSerializer(many=True, read_only=True)

    class Meta:
        model = Episode
        fields = (..., 'guest', 'topic')
        depth = 1

I have put some data on for guests and topics but I can't get them showing up on the API. I've also tried 'Guest.episodes.through' like I do have it on the admin for Inline Admin Classes but that didn't change anything.

Helmi
  • 489
  • 7
  • 25
  • Can you post your Episode model as well, since that's the one on which your last serializer is based? And do you have `related_names` set for any of these m2m relationships? – souldeux Jun 01 '18 at 02:41
  • @souldeux I just did add the Episode model. No, I didn't set `related_names` so far. I read they are optional? – Helmi Jun 01 '18 at 05:09

1 Answers1

2

Your Episode model does not have any forward relationships to your Guest or Topic models. For that reason, your Episode serializer should seek to serialize guest_set and topic_set instead of guest and topic.

If you specify a related name for those M2M field, you can customize the naming convention here. Right now you have this:

class Guest(models.Model):
    episodes = models.ManyToManyField(Episode)
    ...

Which means that to get to all the Guests associated with a given Episode called ep, the reverse lookup would be ep.guest_set.all(). Define a related name and you can call the middle term whatever you want:

class Guest(models.Model):
    episodes = models.ManyToManyField(Episode, related_name='guests')
    ...

With this you could use ep.guests.all(), and you could update your Episode serializer to look for guests as opposed to guest_set.

souldeux
  • 3,615
  • 3
  • 23
  • 35