44

由于 Django 1.5 原始帖子数据可以通过 request.body 访问。

在我的应用程序中,我有时会通过表单发送数据,有时还会收到原始数据(例如 json)。有没有办法编写这样一个不会失败的函数?

def get_post_var(request, name):
    result = request.POST.get(name)
    if result:
        return result

    post_body = dict(urlparse.parse_qsl(request.body))
    result = post_body.get(name)
    if result:
        return result

    return None
4

6 回答 6

56

使用request.data而不是request.body.

request.data不再读取数据流。

于 2019-03-11T10:32:27.240 回答
45

如果 (1) 请求方法是 POST,(2) 请求的 POST 字典在中间件中访问,或者(3) 在视图函数中访问,则该错误You cannot access body after reading from request's data stream将在请求上触发。即使错误的真正原因是(2),也会在(3)上引发错误。process_requestprocess_viewrequest.body

为了解决错误,您需要检查中间件的访问位置request.POST并对其进行修改,使其不再访问request.POST

Django 文档说中间件不应该访问request.POST,这是忽略该建议的后果之一。

另请查看有关问题的 Django 票证,其中包括注释:

[M] 命中 request.POST 的中间件应该(通常)被认为是一个错误。这意味着视图将无法设置任何自定义上传处理程序、执行请求正文的自定义解析或在文件上传被接受之前强制执行权限检查。

于 2015-02-21T03:59:33.900 回答
13

除了 Adam Easterling 的回答之外,值得注意的是 Django 本身“违反”了在中间件中使用 request.POST的提示:

CsrfViewMiddleware 类可以被认为是一个异常,因为它提供了 csrf_exempt() 和 csrf_protect() 装饰器,它们允许视图显式控制应该在什么时候进行 CSRF 验证。

哪个不能消除违规IMO

于 2016-03-02T16:57:34.777 回答
3

对于那些有兴趣知道的人,我遇到了这个问题:

从请求的数据流中读取后无法访问正文

当我在“REST_FRAMEWORK”中添加“oauth2_provider.contrib.rest_framework.OAuth2Authentication”时,就像在settings.py中一样:

REST_FRAMEWORK = {
   ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
      ...
       'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
      ...
    ),

当然,禁用它会起作用,但不是我会引以为豪的解决方法。

于 2020-10-30T01:07:54.760 回答
0

将 @csrf_exempt 放在我的视图函数之前后,我能够阅读我的 request.POST 。因为 CSRF 中间件访问的是 POST 数据。

于 2018-05-19T16:37:49.167 回答
-1

对于那些没有准备好正文或 POST 的错误,当我在 process_view 中间件中使用这行代码时遇到了同样的错误::

   event = request.event if 'event' in request else None

由函数顶部的设置 request.event = None 解决,因此我可以使用:

    event = request.event
于 2019-08-04T13:59:16.267 回答