44

I have three models — articles, authors and tweets. I'm ultimately needing to use Django REST Framework to construct a feed that aggregates all the objects using the Article and Tweet models into one reverse chronological feed.

Any idea how I'd do that? I get the feeling I need to create a new serializer, but I'm really not sure.

Thanks!

Edit: Here's what I've done thus far.

app/serializers.py:

class TimelineSerializer(serializers.Serializer):
    pk = serializers.Field()
    title = serializers.CharField()
    author = serializers.RelatedField()
    pub_date = serializers.DateTimeField()

app/views.py:

class TimelineViewSet(viewsets.ModelViewSet):
    """
    API endpoint that lists all tweet/article objects in rev-chrono.
    """
    queryset = itertools.chain(Tweet.objects.all(), Article.objects.all())
    serializer_class = TimelineSerializer
3
  • Is your question about how to merge the two timelines of different objects or how to use DRF to output the already-merged timeline? Commented Sep 9, 2013 at 16:54
  • Probably both, on some level ('Fraid I'm a bit of a Django neophyte...). I'll update the code with what I have in a minute, but I've currently created a new view that uses itertools.chain() to create a queryset combining Tweet.objects.all() and Article.objects.all() and gives it to a new serializer that lists the fields common to the two models. Am I anywhere near on the right path? Commented Sep 9, 2013 at 17:10
  • 2
    You can use this - github.com/Axiologue/DjangoRestMultipleModels. Commented Sep 1, 2015 at 11:13

1 Answer 1

27

It looks pretty close to me. I haven't used ViewSets in DRF personally, but I think if you change your code to this you should get somewhere (sorry - not tested either of these):

class TimelineViewSet(viewsets.ModelViewSet):
    """
    API endpoint that lists all tweet/article objects in rev-chrono.
    """
    def list(self, request):
        queryset = list(itertools.chain(Tweet.objects.all(), Article.objects.all()))
        serializer = TimelineSerializer(queryset, many=True)
        return Response(serializer.data)

If you're not wedded to using a ViewSet then a generics.ListAPIView would be a little simpler:

class TimeLineList(generics.ListAPIView):
    serializer_class = TimeLineSerializer

    def get_queryset(self):
        return list(itertools.chain(Tweet.objects.all(), Article.objects.all()))

Note you have to convert the output of chain to a list for this to work.

Sign up to request clarification or add additional context in comments.

4 Comments

I tried the second route, and am getting the following error: "base_name argument not specified, and could not automatically determine the name from the viewset, as it does not have a .model or .queryset attribute." If I replace the "get_queryset" stanza with queryset = list(itertools.chain(Tweet.objects.all(), Article.objects.all())), nothing happens and the whole thing hangs. Any idea what I might be doing wrong?
Woo, totally got the first variant working. Additional notes for anyone finding this: 1. You need from rest_framework.response import Response in views.py. 2. When registering the router in site/urls.py, I needed to specify base_name like so: router.register(r'timeline', views.TimelineViewSet, 'timeline').
Another note — the fields used in the serializer must be present in both models fed to itertools.chain(), merely setting "required=False" for the unique field in the serializer won't do anything.
you should ideally post the comment as an answer or add the edit to the question so that it helps someone else

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.