2
votes

My API is going to list a bunch of episodes of a podcast. The list itself should be stripped down and not have a lot of data to be small enough to pull the whole list at once. Here's my DRF serializer class

class EpisodeSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Episode
        fields = ('url', 'id', 'title', 'subtitle', 'show_id', 'published_at', 'updated_at')

This works just fine using this view

class EpisodeViewSet(viewsets.ModelViewSet):
    queryset = Episode.objects.all().order_by('-published_at')
    serializer_class = EpisodeSerializer

The `HyperlinkedModelSerializer' also links the episodes to their own detail views but obviously uses the same view by default. Now what I want is to be more detailled on the detail view so what I did was:

router.register(r'episodes', views.EpisodeViewSet)
router.register(r'episode', views.EpisodeDetailViewSet)

added this route and made a new view

class EpisodeDetailViewSet(viewsets.ModelViewSet):
    queryset = Episode.objects.all().order_by('-published_at')
    serializer_class = EpisodeDetailSerializer

and the serializer using additional models for more details

class EpisodeDetailSerializer(serializers.ModelSerializer):
    chapters = ChapterMarkSerializer(source='chaptermark_set', many=True)
    media = MediaClipSerializer(source='mediaclip_set', many=True)
    show = ShowSerializer()

    class Meta:
        model = Episode
        fields = ('url', 'id', 'title', 'subtitle', 'show', 'published_at', 'updated_at','description', 'show_notes', 'cover_image', 'updated_at', 'chapters', 'media')
        depth = 1

Now this basically works for each Episode now using the /episode/123 format but it also renders all episodes with full details under the /episode URL and it overwrites the /episodes URL which doesn't show on the API's index page anymore.

I assume that's due to the model = Episode entry that overwrites the other Class for being responsible for that Model?

I think that my new view somehow needs to be restricted to not list all episodes and then the two views/serializers need to coexist somehow but I feel like i'm stuck here and the docs really don't help me out.

Thanks for any advise.

1

1 Answers

5
votes

Instead of additional viewset (which could make your code more complex for maintain) I suggest simple override get_serializer_class of EpisodeViewSet. Using self.action attribute you can check current action and use another serializer for detailed response only:

class EpisodeViewSet(viewsets.ModelViewSet):
    queryset = Episode.objects.all().order_by('-published_at')

    def get_serializer_class(self):
        if self.action == 'retrieve':
            return EpisodeDetailSerializer
        return EpisodeSerializer

Now you dont need EpisodeDetailViewSet and in urls.py you will have only one routnig:

router.register(r'episodes', views.EpisodeViewSet)