Django 不接受来自 python-requests.patch() 的数据

Posted

技术标签:

【中文标题】Django 不接受来自 python-requests.patch() 的数据【英文标题】:Django not accepting data from python-requests.patch() 【发布时间】:2016-02-11 11:06:26 【问题描述】:

我正在尝试通过 http PATCH 请求将使用 python 运行的服务中的数据发送到另一个使用 Django API Rest Framework 使用 requests 运行的 Django。

SomeAccount 有一个字段 appUserId,现在是 -1

这里是知道app_user_id(例如=77)的some_sender.py

auth = ('someusrname', 'somepwd')
data = "appUserId": app_user_id
url = 'myapi:8000/someaccounts/1'
r = requests.patch(url, data=data, auth=auth)
print r.status_code
#> 200

当我在 GET /someaccounts/1 检查项目的值时,它仍然有 appUserId=-1

在调试时,在 Django 中我收到了请求,但没有任何数据 - 它只是一个空字典。

这是我在 Django 中的样子:

mysite/myapp/urls.py

from django.conf.urls import include, url
from rest_framework import routers
from . import views

router = routers.DefaultRouter()

router.register(r'someaccount', views.SomeAccountViewSet)
# ...
urlpatterns = [
    url(r'^', include(router.urls)),
    # ...
]

mysite/myapp/models.py

from django.db import models
# ...
class SomeAccount(models.Model):
    """
    Some account can include all the data related to some user's account.
    """
    # ...
    appUserId = models.BigIntegerField(blank=True, null=True)

mysite/myapp/views.py

class SomeAccountViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows some accounts to be viewed or edited.
    """
    queryset = SomeAccount.objects.all()
    serializer_class = SomeAccountSerializer

mysite/myapp/serializers.py

from models import SomeAccount
# ...
class SomeAccountSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()

    class Meta:
        model = SomeAccount
        fields = ('url', 'id', 'appUserId')
        depth = 3
        partial = True

    def update(self, someAccount, account_data):
        if 'appUserId' in account_data:
            someAccount.appUserId = account_data.pop('appUserId')
        someAccount.save()
        return someAccount

SomeAccountSerializer 中调试传入请求时,我得到以下值:

account_data: initial_data: <QueryDict: > someAccount: 'appUserId': -1, 'id': 1

我尝试通过 Postman Google Chrome 插件发送相同的值,并且成功了。

我也尝试设置content-type 标头:

application/x-www-form-urlencoded:

requests.patch(
    url, data=data, auth=auth,
    headers='content-type': 'application/x-www-form-urlencoded'
)

application/form-data:

requests.patch(
    url, data=data, auth=auth,
    headers='content-type': 'application/form-data'
)

application/json:

requests.patch(
    url, json=json.dumps(data), auth=auth,
    headers='content-type': 'application/json'
)

没有成功。

编辑: python-requests 正在正确发送请求。问题可能在于 Django 是如何处理它的。

【问题讨论】:

检查请求的响应正文,也许对问题有一些了解。 这也有帮助,谢谢!结果发现服务器端和 URL 出现了一些错误(我可能还在 url 字符串的末尾缺少了一个 /。所以它应该是 GET /someaccounts/1/ 【参考方案1】:

刚刚遇到同样的问题。缺少 URL 上的尾部斜杠。当 Django 重定向到带有斜杠的 URL 时,它似乎丢弃了 PATCH 的有效负载。

【讨论】:

【参考方案2】:

您应该检查您的网络流量,以确定问题出现在哪里。如果我使用

import requests

app_user_id = 7
auth = ('someusrname', 'somepwd')
data = 'appUserId': app_user_id
url = 'http://localhost:8000/someaccounts/1'

r = requests.put(url, data=data, auth=auth)
print r.status_code

并使用 netcat (nc -l 8000) 打开一个本地套接字,我正在获取编码的数据形式:

PUT /someaccounts/1 HTTP/1.1
Host: localhost:8000
Content-Length: 11
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: python-requests/2.8.1
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Authorization: Basic c29tZXVzcm5hbWU6c29tZXB3ZA==

appUserId=7

【讨论】:

好的,这里也是。它似乎仍在发送数据。 (仅差异:User-Agent: python-requests/2.6.0 CPython/2.7.10 Darwin/14.5.0

以上是关于Django 不接受来自 python-requests.patch() 的数据的主要内容,如果未能解决你的问题,请参考以下文章

Django:只接受来自我的应用程序的请求

Django 和 Restful API

如何不使用 Django 的管理员登录视图?

Django中的详细模板不接受值

Django 时区字段不接受所有 pytz 时区

Select2 与 Django 不接受选择