Python Django REST框架奇怪的结果

Python Django REST框架奇怪的结果,python,django,django-rest-framework,Python,Django,Django Rest Framework,出于某种原因,我在发送POST请求时遇到了一些奇怪的问题 这是我的URL设置: http://host/api/user/1/edit/ http://host/api/address/search/ 其中,/api/是api根,user是模型,1是用户ID,edit和search是自定义函数 这是在views.py中: class UserViewSet(viewsets.ModelViewSet): ... def post(self, request, pk, *arg

出于某种原因,我在发送
POST
请求时遇到了一些奇怪的问题

这是我的URL设置:

http://host/api/user/1/edit/
http://host/api/address/search/
其中,
/api/
是api根,user是模型,1是用户ID,
edit
search
是自定义函数

这是在
views.py中:

class UserViewSet(viewsets.ModelViewSet):
    ...

    def post(self, request, pk, *args, **kwargs):
        ... (processing)

    @detail_route(methods=['post'])
    def edit(self, request, pk, *args, **kwargs):
        ... (processing)

class AddressViewSet(viewsets.ModelViewSet):
    ...

    def post(self, request, *args, **kwargs):
        ... (processing)

    @detail_route(methods=['post'])
    def search(self, request, *args, **kwargs):
        ... (processing)
router = DefaultRouter()
router.register(r'user', views.UserViewSet)
router.register(r'address', views.AddressViewSet)

urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^authentication/', include('rest_framework.urls', namespace='rest_framework'))
]
这在
url.py中:

class UserViewSet(viewsets.ModelViewSet):
    ...

    def post(self, request, pk, *args, **kwargs):
        ... (processing)

    @detail_route(methods=['post'])
    def edit(self, request, pk, *args, **kwargs):
        ... (processing)

class AddressViewSet(viewsets.ModelViewSet):
    ...

    def post(self, request, *args, **kwargs):
        ... (processing)

    @detail_route(methods=['post'])
    def search(self, request, *args, **kwargs):
        ... (processing)
router = DefaultRouter()
router.register(r'user', views.UserViewSet)
router.register(r'address', views.AddressViewSet)

urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^authentication/', include('rest_framework.urls', namespace='rest_framework'))
]
我遇到的奇怪的事情是:

如果我正在使用
httpie
并发送
POST
编辑请求,如下所示:

http POST http://host/api/user/1/edit/ name="john" address="google.com"
然后
def post
中的内容将永远无法执行。如果我让浏览器发送一个
POST
请求,情况也是如此

但是,如果我通过执行以下操作发送
POST
搜索请求:

http POST http://host/api/address/search/ name="john"
在这种情况下,
defsearch
中的内容将永远不会执行,而只有
defspost
中的内容才会执行

我能看到的唯一区别是,对于
edit
,有一个额外的
pk
(本例中的值为
1
),而“搜索”没有
pk

有人知道为什么会这样吗?在视图集中定义post()并没有任何作用,这是针对APIView派生类的,这对我来说真的很困惑。如果要覆盖视图集中的默认对象创建,可以

def create(self, request, *args, **kwargs): ... do stuff ... def创建(self、request、*args、**kwargs): ... 做些事情。。。 甚至更好

def perform_create(self, serializer): ... do stuff ... serializer.save() def执行_创建(自、序列化程序): ... 做些事情。。。 serializer.save() 至于地址,您需要使用列表路由装饰器而不是详细路由。细节路径用于对单个对象进行操作,列表路径用于列表。所以/address/search/应该是列表路线,/address/1/search/应该是详细路线。请注意,我认为post()中的代码在这两种情况下都不会运行


下面是一段相关的文档

当向rest框架提交post请求时,请求被映射到视图集上的方法,而Django视图只调用
post
方法

当发布到
user/{pk}/
时,您的请求将映射到
UserViewSet.create
方法。对
user/{pk}/edit/
的post请求映射到您的
UserViewSet.edit
方法。在这两种情况下,都不会调用
UserViewSet.post

似乎当您发布到不存在的自定义url时,会调用
post
方法(可能是一种回退)。在您的例子中,
address/search/
不是有效的url,而是将端点定义为
address/{pk}/search/

如果要访问
地址/search/
,则需要更新搜索方法,以使用
列表路径
装饰器,而不是
详细路径

class AddressViewSet(viewsets.ModelViewSet):
    ...

    @list_route(methods=['post'])
    def search(self, request, *args, **kwargs):
        ... (processing)

希望这有助于为您澄清问题。

我很好奇如何使用浏览器发送
POST
数据?我使用Jquery AJAX发送数据。您可以在shell中尝试curl:
curl-I-X POST-H'内容类型:application/json'-d'{“name”:“john”,“address”:“google.com”}http://host/api/user/1/edit/
?看起来不错。返回与使用
POST
相同的内容,我100%确定在执行
search
时代码会运行。我已经尝试将
响应(“post”)和
响应(“函数”)
放在post中,并运行了两次以进行测试。您的post可能缺少实际代码中的某些内容。如果代码是按照您发布的方式构造的,那么就不会调用post()。假设您使用的是最新版本的REST框架。不管怎样,试试我的建议。它来自这里,类似这样:是的,您可能会注意到post()不在该页面的预定义方法列表中。post()用于APIView,而不是ViewSet。抱歉,我将其链接错了: