【问题标题】:Exception: You cannot access body after reading from request's data stream例外:从请求的数据流中读取后,您无法访问正文
【发布时间】:2023-03-14 22:15:02
【问题描述】:

Since Django 1.5 raw post data is accessible via 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

【问题讨论】:

  • “有时是纯数据”是什么意思。如果是 POST 请求,django 将负责填充 request.POST,无论数据是通过表单提交还是通过 curl 或其他任何方式提交。
  • 我的意思是非表单数据(例如 json),如下所述:docs.djangoproject.com/en/1.5/ref/request-response/…

标签: django exception post request


【解决方案1】:

使用request.data 而不是request.body

request.data 不再读取数据流。

【讨论】:

  • 这是修复错误的实际答案。应该有更高的赞成票。
  • 我在 Django 1.4 中使用 request.data 得到 AttributeError: 'WSGIRequest' object has no attribute 'data'。关于如何解决这个问题的一些想法?
  • @CarMoreno @Ulvi 我相信 request.data 是 DRF 的东西。传递给 DRF 视图的 request 对象与传递给普通 django 视图的 request 对象不同。
  • @TimHong 这解决了问题 when 问题是由 DRF 引起的,但是 1)情况并非总是如此,2)答案中没有解释并让人们感到困惑, 3) 在问题中没有提到 DRF。当然,这可能 90% 的时间是由 DRF 引起的,但亚当的回答是最普遍和最正确的解释,适用于任何情况。
【解决方案2】:

如果 (1) 请求方法是 POST,(2) 在中间件中访问请求的 POST 字典,process_requestprocess_view 和 (3) 在访问视图函数request.body。即使错误的真正原因是 (2),也会在 (3) 上引发错误。

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

Django 文档说 middleware should not access request.POST,这是忽略该建议的后果之一。

还可以查看this Django ticket on the issue,其中包括注释:

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

【讨论】:

  • 需要补充的是,这不仅适用于request.POST,也适用于request.body
  • 我实际上需要访问 request.data 我该怎么做?
  • 如果我使用request.data,我得到的请求没有属性数据
【解决方案3】:

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

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

当我添加“oauth2_provider.contrib.rest_framework.OAuth2Authentication”时 在 settings.py 中的“REST_FRAMEWORK”中:

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

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

【讨论】:

  • 您必须在 APIView 顶部显式使用 authentication_classes = [] 才能解决此问题
【解决方案4】:

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

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

这不会消除 IMO 的违规行为

【讨论】:

  • 确实这让我很烦恼。如果您要读取请求正文(而不是通过 POST/FILES),则解决方案/解决方法是使用 PUT 而不是 POST。
【解决方案5】:

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

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

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

    event = request.event

【讨论】:

    【解决方案6】:

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

    【讨论】:

      猜你喜欢
      • 2020-11-08
      • 2021-03-13
      • 2020-11-12
      • 1970-01-01
      • 2019-11-21
      • 1970-01-01
      • 2014-02-18
      • 2020-01-29
      • 2017-06-19
      相关资源
      最近更新 更多