我正在使用Django Rest Framework,并且希望能够通过DELETE
到/api/content/<int:pk>/
删除Content实例。我不想要实现任何方法来响应GET
请求。
当我包含如下的.retrieve()
方法时,DELETE
请求起作用:
class ContentViewSet(GenericViewSet):
def get_queryset(self):
return Content.objects.filter(user=self.request.user)
def retrieve(self, request, pk=None):
pass #this works, but I don't want .retrieve() at all
def delete(self, request, pk=None):
content = self.get_object()
#look up some info info here
content.delete()
return Response('return some info')
如果我将.retrieve()
替换为RetrieveModelMixin
,它也会起作用。但是,如果我同时删除了这两个选项,则会收到以下错误消息。
django.urls.exceptions.NoReverseMatch:找不到“内容详细信息”的反向内容。 “ content-detail”不是有效的视图函数或模式名称。
我还没有测试,但是我假设PUT
和PATCH
也会发生同样的事情。
我的问题是:
DELETE
方法的情况下允许.retrieve()
,并且.retrieve()
的情况下DRF无法创建urlconf? 更新:由于删除.retrieve()
方法而导致测试失败并完成了错误回溯
from rest_framework.test import APITestCase, APIClient
from myapp.models import Content
class ContentTestCase(APITestCase):
def setUp(self):
self.content = Content.objects.create(title='New content')
self.client = APIClient()
def test_DELETE_content(self):
url = reverse('content-detail', kwargs={'pk':self.content.pk})
response = self.client.delete(url)
self.assertEqual(response.status_code, 200)
结果:
Traceback (most recent call last):
File "myproject/myapp/tests.py", line 548, in test_DELETE_content
url = reverse('content-detail', kwargs={'pk':self.content})
File "python3.6/site-packages/rest_framework/reverse.py", line 50, in reverse
url = _reverse(viewname, args, kwargs, request, format, **extra)
File "python3.6/site-packages/rest_framework/reverse.py", line 63, in _reverse
url = django_reverse(viewname, args=args, kwargs=kwargs, **extra)
File "python3.6/site-packages/django/urls/base.py", line 90, in reverse
return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
File "python3.6/site-packages/django/urls/resolvers.py", line 636, in _reverse_with_prefix
raise NoReverseMatch(msg)
django.urls.exceptions.NoReverseMatch: Reverse for 'content-detail' not found. 'content-detail' is not a valid view function or pattern name.
答案 0 :(得分:1)
- 如何在不实现
.retrieve()
方法的情况下允许DELETE?
只需从视图类中删除 retrieve()
方法。也就是说,GenericViewSet
不会提供任何 HTTP操作 ,除非它是在您的类中定义的。
因此,以下内容将是您的代码段,
class ContentViewSet(GenericViewSet):
def get_queryset(self):
return Content.objects.filter(user=self.request.user)
def delete(self, request, pk=None):
content = self.get_object()
# look up some info info here
content.delete()
return Response('return some info')
或者您可以在此处使用 mixin classes
,
from rest_framework.mixins import DestroyModelMixin
class ContentViewSet(DestroyModelMixin, GenericViewSet):
def get_queryset(self):
return Content.objects.filter(user=self.request.user)
- 为什么在未实施
.retrieve()
的情况下DRF无法创建urlconf?
我不确定您如何定义网址。当我尝试使用 DRF路由器 时,它只是为定义的操作创建URL conf。
由于您已定义 GET
,因此在端点上已执行 DELETE
和 retrieve()
方法。
希望有帮助:)
答案 1 :(得分:0)
我对第1部分的解决方案是包括mixin但限制http_method_names
:
class ContentViewSet(RetrieveModelMixin, GenericViewSet):
http_method_names = ['delete']
...
但是,我仍然完全不知道为什么必须包含RetrieveModelMixin
。
答案 2 :(得分:0)
在这里很容易猜到,但是您使用SimpleRouter
还是DefaultRouter
来构建urlpatterns
吗?
如果是这样,那就是您的问题。路由器使用视图集,并期望实现所有方法。更多信息here
您所能做的就是将url
添加到urlpatterns
,就像通常使用.as_view()
方法在django上所做的那样。