【问题标题】:Delete method on Django Rest Framework ModelViewSetDjango Rest Framework ModelViewSet 上的删除方法
【发布时间】:2018-02-13 16:30:10
【问题描述】:

我已尝试使用 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()

destroy 和 perform destroy 函数是我尝试过的,但没有成功。这是我尝试时返回的内容:

{ "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

【问题讨论】:

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


    【解决方案1】:

    这里的问题是您将DELETE 请求发送到错误的网址。看看DefaultRouter docs。它会在您的viewset 中自动生成您的网址:

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

    解决您的问题的方法是不要将manuscript_id 作为请求的 JSON 正文传递

    {
        "manuscript": 7,
    }
    

    但是要直接传给url:

    DELETEhttp://localhost:8000/manuscripts-api/manuscripts/7/

    您只需像这样注册您的视图集:

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

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

    【讨论】:

    • 我试过了,但是当我用 as_view() TypeError: The `actions` argument must be provided when calling `.as_view()` on a ViewSet. For example `.as_view({'get': 'list'})` 注册 url 时出现这个错误你知道为什么吗?
    • @AngelF 我认为当你使用ViewSet,而不是ModelViewSet 时,你应该提供method -> action 映射(这正是{'get': 'list'}。你告诉get 方法将调用 list 方法。在 ModelViewSet 上,这已设置。
    【解决方案2】:
    from rest_framework.response import Response
    from rest_framework import status
    
    
    
    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)
    

    使用它,它会起作用

    【讨论】:

    • 嗨,我和 perform_destroy 一起去了。它仍然告诉我“不允许使用方法 \"DELETE\"。”不允许,因此我添加了其他信息。
    • 它仍然说方法不允许,我是以正确的 json 格式发送的?我如何准确地告诉它要删除哪个手稿?我用包括查询在内的其他信息更新了我的问题
    • 我不知道“响应”是 Django 的东西还是 Django 休息框架的东西。来自 Django rest 框架的示例具有相同的内容,但没有显示从何处导入它,通常您会让 Django 返回一个 HttpResponse。 “响应”不在 Django 文档中。你能澄清一下吗?更新:我发现您使用 from rest_framework.response import Response 导入它
    猜你喜欢
    • 2021-08-10
    • 2014-08-24
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 2021-10-05
    相关资源
    最近更新 更多