Nested resources in Django REST Framework

11,508

Solution 1

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.

Solution 2

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)

    

Solution 3

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.

Share:
11,508

Related videos on Youtube

Tal Peretz
Author by

Tal Peretz

Updated on June 04, 2022

Comments

  • Tal Peretz
    Tal Peretz almost 2 years

    I wish to implement my new API with a nested resource.

    Example: /api/users/:user_id/posts/
    

    Will evaluate to all of the posts for a specific user. I haven't seen an working example for this use case, maybe this isn't the right way for implementing rest API?

    • Mykel
      Mykel over 9 years
      Where are you stuck? This is fairly straight forward, assuming you already setup OAUTH2.
    • Tal Peretz
      Tal Peretz over 9 years
      How my serlizers will be? which related fields to choose?
    • Kermit
      Kermit almost 5 years
  • Danilo Cabello
    Danilo Cabello about 9 years
    Link decorator got removed in favor of listed_route and detail_rout decorators: github.com/tomchristie/django-rest-framework/commit/…
  • Ankit Popli
    Ankit Popli almost 8 years
    @PranjalMittal use @detail_route(methods=['post']). Checkout the doc here
  • zentia
    zentia almost 2 years
    With action decorator: @action(detail=False, methods=["GET"])