在 Django 中获取请求正文作为字符串

Posted

技术标签:

【中文标题】在 Django 中获取请求正文作为字符串【英文标题】:Get request body as string in Django 【发布时间】:2015-06-13 09:03:21 【问题描述】:

我正在向 Django 服务器发送一个带有 JSON 正文的 POST 请求(相当标准)。在服务器上,我需要使用json.loads() 对此进行解码。

问题是如何获取字符串格式的请求正文?

我目前有以下代码:

body_data = 
if request.META.get('CONTENT_TYPE', '').lower() == 'application/json' and len(request.body) > 0:
    try:
        body_data = json.loads(request.body)
    except Exception as e:
        return HttpResponseBadRequest(json.dumps('error': 'Invalid request: 0'.format(str(e))), content_type="application/json")

但是,这会产生错误the JSON object must be str, not 'bytes'

如何在应用正确编码的情况下以字符串形式检索请求正文?

【问题讨论】:

request.read() 能完成这项工作吗? @dhke,不,它给出了相同的结果,这实际上让我感到惊讶。 request.body.decode('utf-8') 似乎有效,但我不确定这是否是最好的方法? 【参考方案1】:

请求正文request.body 是一个字节字符串。在 Python 3.0 到 3.5.x 中,json.loads() 将只接受 unicode 字符串,因此您必须在将 request.body 解码之前将其传递给 json.loads()

body_unicode = request.body.decode('utf-8')
body_data = json.loads(body_unicode)

在 Python 2 中,json.loads 将接受 unicode 字符串或字节字符串,因此不需要解码步骤。

在解码字符串时,我认为您可以安全地假设 'utf-8' - 我找不到确切的来源,但请参阅下面来自 jQuery docs 的引用:

注意:W3C XMLHttpRequest 规范规定字符集始终为 UTF-8;指定另一个字符集不会强制浏览器更改编码。

在 Python 3.6 中,json.loads() accepts bytes or bytearrays。因此,您不需要解码 request.body(假设它以 UTF-8 编码)。

【讨论】:

utf-8也是decode()方法的第一个参数的默认值(检查help(bytes.decode) 在 Python >= 3.6 中,json.loads 也可以接受 bytes 参数,并且假定它以 UTF-8、UTF-16 或 UTF-32 编码。 docs.python.org/3/library/json.html#json.loads UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfb in position 9: invalid start byte python 3 7 7 @CoffeeinTime 该错误表明请求正文不是有效的 utf-8。如果您控制它,请修复客户端,如果您不控制,请添加适当的错误处理。【参考方案2】:

如果您的目标是使用 JSON 获得刚刚发送到服务器的数据的字典,请省去自己解码正文的麻烦,并使用 django 已经提供的request.POST 类字典对象 -开箱即用。

所以假设你 POST 到服务器:

 'foo': 'bar' 

那么下面的方法

def my_handler(request):
    foo = request.POST['foo']
    print(foo)

bar 打印到控制台

【讨论】:

好吧,我在阅读 django 时遇到了这个问题,意识到有一个更简单的解决方案,所以我发布了它。那是一件坏事?这是一个较老的问题有关系吗?恕我直言,它仍然相关 谢谢,这正是我所需要的!发帖总比不发帖好,永远不知道对谁有帮助。 这个答案不正确。 request.POST 仅在请求正文是表单编码的情况下才有效。如果数据是 json 编码的,它将不起作用。【参考方案3】:

我相信您收到此请求的另一端在发送请求之前不会将数据转换为 JSON。您必须在发送之前将数据转换为 JSON,或者只是尝试在您的视图中访问 request.body。

【讨论】:

感谢您的回答。我认为它是有效的 json - 如果我使用 request.body.decode('utf-8') 那么它可以工作。你会说有理由不这样做吗?

以上是关于在 Django 中获取请求正文作为字符串的主要内容,如果未能解决你的问题,请参考以下文章

Alamofire POST 请求,正文中有一个简单的字符串作为参数,标头仍然显示缺少的参数值

django 获取request请求对象及response响应对象中的各种属性值

如何在 Spring REST 控制器中获取原始 JSON 正文?

在 Spring MVC 中使用 curl 将字符串值数组作为请求正文发布

Laravel 获取正文请求并避免查询字符串参数

REST API 最佳实践:查询字符串中的参数与请求正文中的参数