0

How to add suffix url in ModelViewSet

Serializer

class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = '__all__'

    def update(self, instance, validated_data):
        ...
        ...

ModelViewSet

I'm doing a custom partial update

class CommentViewSet(viewsets.ModelViewSet):
    queryset = Comment.objects.all()
    serializer_class = CommentSerializer
    http_method_names = ['get', 'patch', 'head', 'options']

    def partial_update(self, request, *args, **kwargs):
        super(CommentViewSet, self).partial_update(
            request, *args, **kwargs)

        return Response({
            "data": request.data,
            ...
            ...
        })

Urls

router = routers.DefaultRouter()
router.register(
    "comments",
    CommentViewSet
)

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

Currently have this, but I want to add a suffix

url: http://localhost:8000/api/v1/comments/{id}

I want to do something like this

url: http://localhost:8000/api/v1/comments/{id}/update_or_whatever

2
  • you can try annotation @action django-rest-framework.org/api-guide/viewsets/…. Example, with @action, url_path='update_or_whatever', detail=True, you will have url like http://localhost:8000/api/v1/comments/{id}/update_or_whatever/ Commented Dec 8, 2020 at 8:27
  • @NgocPham Actually I was doing it like that, but I have exception, Cannot use the @action decorator on the following methods, as they are existing routes: partial_update Commented Dec 8, 2020 at 8:51

2 Answers 2

1

What you want to do does not follow the REST architecture and popular practice. In REST, each endpoint represents a resource. The actions on the resource are represented by HTTP methods. So if you have the comments resource accessible through this url http://localhost:8000/api/v1/comments/, you can create (POST), get the list (GET) on the list endpoint and edit(PUT and PATCH), fetch a single comment (GET) and delete(DELETE) using the detail endpoint. In this way, you don't need to explicitly name the URL according to the action like http://localhost:8000/api/v1/comments/{id}/update. This is the architecture that DRF is built on and hence why you have this url style. Of course, there are actions like login and others that may not fit into this architecture and that's why DRF provides custom actions. But you should not use it to override the default actions mapped to HTTP methods

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

1 Comment

Thanks, your comments very helpful
0

Another magic from DFR

https://www.django-rest-framework.org/api-guide/viewsets/#viewset-actions

Only change what u need in the view and add this action decorator.

In your views.py

    @action(methods=['get'], detail=True, permission_classes=[IsAuthenticated])
    def get_file(self, request, pk=None):
        if pk is None:
            raise ValueError("Found empty filename")
        obj = self.get_queryset().filter(pk=pk).first()
        if obj and obj.image_file:
            return FileResponse(obj.image_file, content_type="image/jpeg")

        return Response(
                'Nothing to show',
                status=status.HTTP_400_BAD_REQUEST)

Comments

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.