8

I've got two models, one of a box and one of box comment:

class BoxViewSet(viewsets.ModelViewSet): queryset = Box.objects.all() permission_classes = IsAuthenticated, serializer_class = BoxSerializer

class BoxCommentViewSet(viewsets.ModelViewSet): model = BoxComment serializer_class = CommentSerializer permission_classes = IsAuthenticated def get_queryset(self): # this should return a queryset that filters based on the # box in the route return BoxComment.objects.all()

If I've set up a router to make Boxes available at /boxes/ and specific boxes available at /boxes/{id}/ using
router.register(r'boxes', feed.views.BoxViewSet)
is it possible to make comments available at /boxes/{id}/comments/? Or should I just set up a separate route and use GET/POST parameters to refer to specific boxes?

WFT
  • 267
  • 3
  • 11

2 Answers2

11

I don't see any problems to do this (I already use it in my projects and everything is fine) - all you need is an url with box_id kwarg. This has nothing with "nesting routers", it's just another endpoint with explicit filtering by url kwarg.

router.register(r'boxes/(?P<box_id>\d+)/comments', BoxCommentViewSet)

Then just filter out corresponding comments in get_queryset

class BoxCommentViewSet(viewsets.ModelViewSet):

    def get_queryset(self):
        return BoxComment.objects.filter(
            box=self.kwargs['box_id']
        )
Ivan Klass
  • 6,407
  • 3
  • 30
  • 28
  • I am a novice in Django development, can you please tell me what was get_queryset was used here for ? won't queryset = Comment.objects.all() be enough own its own. – Mueez Khan Oct 21 '21 at 13:42
5

This is typically referred to as nested routers (or nested viewsets), and it's generally not recommended in Django REST Framework. If possible, you should use a flat representation in your APIs, so

/boxes/{id}/comments

would actually be

/comments/?box={id}

This is considerably easier to implement with Django REST Framework using the built-in filtering (and maybe django-filter). It's guaranteed not to break in future versions of DRF, and it's the recommended way at the moment. The HTTP API guidelines might be a good read if you're interested why, and there's a discussion about it there as well.


Now, you can't always avoid using nested routers. I've written about it in the past, using the third-party packages that were available at the time. Since then, drf-extensions has integrated it and it contains a decent implementation of nested routers that should work for most cases.

Community
  • 1
  • 1
Kevin Brown-Silva
  • 40,873
  • 40
  • 203
  • 237