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



由于 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

使用 request.data 而不是 request.body

request.data不会再次读取数据流。

如果 (1) 该请求方法是 POST,(2) 该请求

的 POST 字典在中间件中访问,process_requestprocess_view中访问,以及 (3) 在视图函数中访问request.body,则会在请求时触发错误You cannot access body after reading from request's data stream。在 (3) 上将引发错误,即使错误的真正原因是 (2)。

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

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

另请查看关于这个问题的 Django 票证,其中包括以下注释:

[M]点击请求的空闲软件。开机自检应(通常)被视为 错误。这意味着视图将无法设置任何自定义上传 处理程序,执行请求正文的自定义分析,或强制执行 在接受文件上传之前进行权限检查。

除了Adam Easterling的回答之外,值得注意的是,Django本身"违反了"不使用request的暗示。中间件中的开机自检:

CsrfViewMiddleware类可以被认为是一个例外,因为它 提供 csrf_exempt() 和 csrf_protect() 装饰器,允许 用于显式控制 CSRF 验证应在什么点进行视图 发生。

这并不能消除IMO的违规行为

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

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

当我添加'oauth2_provider.contrib.rest_framework时。OAuth2Authentication'在"REST_FRAMEWORK"中,就像在 settings.py 中这样:

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

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

我能够阅读我的请求。将@csrf_exempt放在我的视图功能之前后开机自检。因为 CSRF 中间件访问 POST 数据。

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

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

通过函数顶部的设置解决 request.event = 无,所以我可以使用:

    event = request.event

我找到了一个技巧,用于我的中间件,

request._read_started = False

完成此操作后,再次准备好身体,它可以工作。

最新更新