Search code examples
python-3.xdjango-rest-frameworkaction

Django rest framework. Setting up dynamic routes


I am setting up an API for a blog. I configured the output of comments for the post Here is a portion of my views.py with @action:

urls.py

router = DefaultRouter()
router.register('api/posts', APIPost)

urlpatterns = [
    path('', include(router.urls)),
]

views.py

...
    @action(methods=['get'], detail=True)
    def comments(self, request, pk=None):
        if request.method == 'GET':
            queryset = Comment.objects.filter(post__id=pk)
            serializer = CommentSerializer(queryset, many=True)
            return Response(serializer.data)
        return Response(status=status.HTTP_403_FORBIDDEN)

Now I can get all comments on a post at.

http://127.0.0.1:8000/api/posts/{post_pk}/comments/

The problem is that I just can't figure out how to get a separate comment at

http://127.0.0.1:8000/api/posts/{post_pk}/comments/{comment_pk}

I keep getting '404 Not Found' error


Solution

  • You should create another CommentViewSet. (docs)

    views.py

    from rest_framework import viewsets
    
    class CommentViewSet(viewsets.ModelViewSet):
        queryset = Comment.objects.all()
        serializer_class = CommentSerializer
    

    urls.py

    from .views import CommentViewSet
    
    router = DefaultRouter()
    router.register("api/posts", APIPost)
    router.register("api/comments", CommentViewSet)
    
    urlpatterns = [
        path('', include(router.urls)),
    ]
    

    and then you can retrieve by making a request to http://127.0.0.1:8000/api/comments/{pk}.


    also, in your code,

    1. @action(methods=['get'], detail=True) it should be @action(methods=['get'], detail=False) instead because the comments action is to retrieve list of all comments. detail=True is for returning a single object.
    2. You don't need to manually check for the if request.method == 'GET' as DRF is already doing that internally because you already specified methods=["get"].