Delete method on Django Rest Framework ModelViewSet

流过昼夜 提交于 2019-12-06 07:58:41

问题


i have tried to delete a single ManuscriptItem instance using Postman to perform my API requests on against the view below:

class ManuscriptViewSet(viewsets.ModelViewSet):
    """Handles creating, reading and updating items."""

    authentication_classes = (TokenAuthentication,)
    serializer_class = serializers.ManuscriptItemSerializer
    permission_classes = (permissions.PostOwnManuscript, IsAuthenticated,)

    def perform_create(self, serializer):
        """Sets the user profile to the logged in user."""
        serializer.save(author=self.request.user)

    def get_queryset(self):
        """
        This view should return a list of all the manuscripts
        for the currently authenticated user.
        """
        user = self.request.user
        return models.ManuscriptItem.objects.filter(author=user)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()

The destroy and perform destroy functions are what I have attempted without success. This is what it returns when i tried:

{ "detail": "Method \"DELETE\" not allowed." }

This is how my URLs are currently registered:

router = DefaultRouter()
router.register('manuscripts', views.ManuscriptViewSet, base_name="manuscripts")  # auto basename for models
router.register('manuscriptlibrary', views.ManuscriptLibraryViewSet, base_name="manuscript_library")
router.register('manuscriptsettings', views.ManuscriptSettingsViewSet)


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

I'm i modifying the ModelViewSet wrong do i need to use another approach because of the nature of ModelViewSet? i expected it to work on Postman when i used an Authorized user to Delete a ManuscriptItem instance. In the docs it said Destroy() method can be used.

Additional information

The URL used is:

http://localhost:8000/manuscripts-api/manuscripts/

The model instance to be deleted from:

class ManuscriptItem(models.Model):
    """Represents a single manuscript's content"""

    author = models.ForeignKey('accounts_api.UserProfile', on_delete=models.CASCADE)
    title = models.CharField(max_length=255)
    content = models.CharField(max_length=99999999)

    def __str__(self):
        """Django uses when it needs to convert the object to a string"""
        return str(self.id)

The way i have tried sending delete requests on postman with json:

{
    "manuscript": 7,
}

Results: Delete Method not allowed

{
    "id": 7,
    "author": 5,
    "title": "niceone",
    "content": "niceone"
}

Results: Delete Method not allowed

Additional Questions/Info:

Don't i need to specify the router register with a pk? I tried this but didnt work either:

router.register('manuscripts/{pk}/$', views.ManuscriptViewSet, base_name="manuscript_detail")

Postman says:

Allow →GET, POST, HEAD, OPTIONS


回答1:


The issue here is that you send DELETE request to the wrong url. Look at the DefaultRouter docs. It generates automatically your urls within your viewset:

Look closely at the DELETE method. It is on the {prefix}/{lookup}/[.format] url pattern. This means that your corresponding router url is manuscripts/<manuscript_id>/, but you try to send DELETE request to manuscripts/ only, which is the above pattern. You see directly from the table that the allowed HTTP methods there are GET and POST only. That's why you receive MethodNotAllowed.

The solution to your problem is not to pass the manuscript_id as a JSON body of the request

{
    "manuscript": 7,
}

But to pass it directly to the url:

DELETE http://localhost:8000/manuscripts-api/manuscripts/7/

And you just register your viewset like:

router.register(r'manuscripts', ManuscriptViewSet.as_view(), name='manuscripts')

As you see, DRF generates the urls automatically for you.




回答2:


def destroy(self, request, *args, **kwargs):
        try:
            instance = self.get_object()
            self.perform_destroy(instance)
        except Http404:
            pass
        return Response(status=status.HTTP_204_NO_CONTENT)

use this and it will work



来源:https://stackoverflow.com/questions/46053922/delete-method-on-django-rest-framework-modelviewset

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!