Django 窗体的访问主体

Django 窗体的访问主体,django,django-forms,Django,Django Forms,我正在存储request.body数据,以便以后可以恢复原始表单。 您似乎只能读取一次request.body。第二次获得RawPostDataException异常时 问题是我在表单中添加了一个forms.FileField。现在,似乎连对request.body的第一次访问都会因RawPostDataException异常而失败 看起来,当以表单形式发送文件时,Django执行了一些操作并读取了request.body对象,实际上是将其锁定在以后的读取中。这甚至在表单对象初始化之前就发生了

我正在存储
request.body
数据,以便以后可以恢复原始表单。 您似乎只能读取一次
request.body
。第二次获得
RawPostDataException
异常时

问题是我在表单中添加了一个
forms.FileField
。现在,似乎连对
request.body
的第一次访问都会因
RawPostDataException
异常而失败

看起来,当以表单形式发送文件时,Django执行了一些操作并读取了
request.body
对象,实际上是将其锁定在以后的读取中。这甚至在表单对象初始化之前就发生了

是虫子吗?否则如何访问
request.body
内容


我正在使用最新的Django(1.11.1)。

您的HTML表单中是否有
enctype=“multipart/form data”
属性?否则,在发送请求中的文件时通常会出现问题。

出于各种原因,Django只允许读取一次帖子正文。由于主体是使用类似于API的文件公开的,因此您无法轻松地再次读取该文件。此外,如果已经读取了数据,则无法进行更改。如果只读取一次POST数据,则会失败,并且由于两个原因,调试非常困难

  • Django只在第二次访问主体时报告其错误,因此很难跟踪第一次访问主体时的错误
  • 许多不同的问题可能导致这种情况。一种方法是在每次读取数据时(在django/http/request.py:HttpRequest.read和HttpRequest.readline中)打印完整的回溯(使用traceback.print_stack())
那么,您是否访问了代码中的某个地方的request.method?您正在使用Django测试客户端吗?还有很多其他原因我不知道

从文件来看

HttpRequest.body»

原始HTTP请求正文为字节字符串。这对于以不同于传统HTML表单的方式处理数据非常有用:二进制图像、XML负载等。对于处理传统表单数据,请使用HttpRequest.POST

在对这个背景进行了大量搜索之后,我偶然发现了一个

在车票上,有明确的说明

假设一个不变量是,在读取一次原始post数据后,您不会访问它,但问题是有两条路径可以读取它,其中一条(非多部分)填充“原始post数据”备忘录(因此,您可以访问原始post数据任意多次),而其中一条(多部分)则不会,后者的基础是多部分数据可能是“大的”,并且会占用内存

但是,说了这么多之后,有一项工作根本不安全,这是事实。通过禁用“django.middleware.csrf.CsrfViewMiddleware”,可以实现这一点

从process_request或process_视图访问request.POST inside将阻止中间件之后运行的任何视图修改请求的上载处理程序,通常应该避免。
该类可以被视为一个例外,因为它提供了和修饰符,允许视图显式地控制CSRF验证应该在什么时候发生。

我强烈认为您应该朝着处理
请求的方向看。相反,POST
。以下是如何序列化和反序列化的示例:

In [1]: from django.test import RequestFactory

In [2]: from django.http.request import QueryDict

In [3]: request = RequestFactory().post('/', {'foo': 'bar', 'bazz': 'spam'})

In [4]: request.POST
Out[4]: <QueryDict: {'foo': ['bar'], 'bazz': ['spam']}>

In [5]: request.POST.urlencode()
Out[5]: 'foo=bar&bazz=spam'

In [6]: QueryDict('foo=bar&bazz=spam')
Out[6]: <QueryDict: {'foo': ['bar'], 'bazz': ['spam']}>

如果目标是保存表单以便以后检索,则可以使用:

form.save(commit=False)

不需要保存
request.Post

是的,我有:
你能改用
request.Post
request.FILES
吗?如何还原原始表单?我通过将
request.body
字符串保存到数据库中来保存原始表单。我通过将
QueryDict(原始字符串)
传递到
Form()
构造函数来恢复它。我无法序列化
request.POST
到数据库中。你说不能序列化
request.POST
到数据库是什么意思?你能发布代码的相关部分吗?我发布了一些代码作为答案,使用
request.POST.urlencode()
而不是
request.body
检查它,解决了这个问题!
form.save(commit=False)