Nested resources in Django REST Framework
To map /api/users/:user_id/posts/
you can decorate a posts
method inside your ViewSet
with @link()
from rest_framework.decorators import link
from rest_framework.response import Response
class UserViewSet(viewsets.ModelViewSet):
model = User
serializer_class = UserSerializer
# Your regular ModelViewSet things here
# Add a decorated method like this
@link()
def posts(self, request, pk):
# pk is the user_id in your example
posts = Post.objects.filter(owner=pk)
# Or, you can also do a related objects query, something like:
# user = self.get_object(pk)
# posts = user.post_set.all()
# Then just serialize and return it!
serializer = PostSerializer(posts)
return Response(serializer.data)
As commented by Danilo Cabello earlier you would use @detail_route
or @list_route
instead of @link()
. Please read the documentation for "Routers", section "Extra link and actions" and "ViewSets", section "Marking extra actions for routing" for detailed explanations.
As commented by Danilo, the @link
decorator got removed in favor of @list_route
and @detail_route
decorators.
Update: @detail_route
& @list_route
got deprecated in favor of @action
.
Here's the alternate solutions:
Solution 1:
@detail_route()
def posts(self, request, pk=None):
owner = self.get_object()
posts = Post.objects.filter(owner=owner)
context = {
'request': request
}
post_serializer = PostSerializer(posts, many=True, context=context)
return Response(post_serializer.data)
Solution 2:
Try drf-nested-routers
. Haven't tried this out yet, but looks promising, many are already using it. Looks like an advanced version of what we are already trying to achieve.
Hope this helps.