在Django Rest Framework ModelViewSet上删除方法

时间:2017-09-05 11:30:50

标签: django django-models django-rest-framework django-views

我尝试使用Postman删除单个ManuscriptItem实例,以针对以下视图执行我的API请求:

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()

我没有成功地尝试破坏和执行破坏功能。这是我尝试时返回的内容:

  

{       “detail”:“方法”DELETE \“不允许”。 }

这是我的网址目前注册的方式:

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))
]

我正在修改ModelViewSet错误我是否需要使用另一种方法,因为ModelViewSet的性质?当我使用授权用户删除ManuscriptItem实例时,我希望它可以在Postman上工作。在文档中它说可以使用Destroy()方法。

其他信息

使用的网址是:

  

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

要删除的模型实例:

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)

我尝试使用json发送删除请求的方式:

{
    "manuscript": 7,
}

结果:不允许删除方法

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

结果:不允许删除方法

其他问题/信息:

我不需要用pk指定路由器寄存器吗?我尝试了这个,但也没有工作:

router.register('manuscripts/{pk}/$', views.ManuscriptViewSet, base_name="manuscript_detail")
邮递员说:

  

允许→GET,POST,HEAD,OPTIONS

2 个答案:

答案 0 :(得分:10)

此处的问题是您向错误的网址发送DELETE请求。看看DefaultRouter docs。它会在viewset

中自动生成您的网址

DefaultRouter class url patterns

仔细查看DELETE方法。它位于{prefix}/{lookup}/[.format]网址格式上。这意味着您的相应路由器网址为manuscripts/<manuscript_id>/,但您尝试仅向DELETE发送manuscripts/请求,这就是上述模式。您可以直接从表中看到允许的HTTP方法只有GETPOST。这就是你收到MethodNotAllowed的原因。

问题的解决方案不是将manuscript_id作为请求的JSON主体传递

{
    "manuscript": 7,
}

但要将其直接传递给网址:

  

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

您只需注册您的视图集:

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

如您所见, DRF 会自动为您生成网址。

答案 1 :(得分:5)

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)

使用它,它将起作用