我正在存储request.body
数据,以便我可以在之后恢复原始表单。
您似乎只能阅读request.body
一次。第二次出现RawPostDataException
异常。
问题是我在表单中添加了forms.FileField
。现在看来,即使第一次访问request.body
也会因RawPostDataException
异常而失败。
看起来当在表单中发送文件时,Django会执行某些操作并读取request.body
对象,实际上将其锁定后再进行读取。甚至在Form对象初始化之前就会发生这种情况。
这是一个错误吗?如何以其他方式访问request.body
内容?
我正在使用最新的Django(1.11.1)。
答案 0 :(得分:1)
我强烈认为您应该朝着使用request.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']}>
如果您想使用字典并将(de)序列化保留到json.dumps
/ json.loads
,还有另一种选择:
In [7]: qdict = QueryDict('', mutable=True)
In [8]: qdict.update({'foo': 'bar', 'bazz': 'spam'})
In [9]: qdict
Out[9]: <QueryDict: {'foo': ['bar'], 'bazz': ['spam']}>
答案 1 :(得分:0)
您的HTML表单中是否有enctype="multipart/form-data"
属性?否则,在您的请求中发送文件时通常会导致问题。
答案 2 :(得分:0)
由于各种原因,Django只允许读取一次POST主体。由于正文使用类似文件的API公开,因此无法再轻松读取该文件。此外,如果您已经阅读过数据,则无法更改upload file handlers。无法仅读取一次POST数据将失败,并且由于两个原因调试很棘手。
那么,您是否在代码中的某处访问了request.method?你在使用Django测试客户端吗?我还有很多其他原因。
来自文档,
HttpRequest.body¶
原始HTTP请求正文作为字节字符串。这对于以不同于传统HTML表单的方式处理数据非常有用:二进制映像,XML有效负载等。对于处理传统表单数据,请使用HttpRequest.POST。
在搜索了这个背景之后,我偶然发现了ticket (HTTPRequest::raw_post_data broken for tests)
在机票中,有明确说明,
这是一个假定的不变量,你不会访问曾经读过一次的raw_post_data,但问题是有两条路径可以读取它,其中一条(非多部分)填充_raw_post_data备忘录(因此你可以随后多次访问raw_post_data),其中一个(多部分)没有,后者基于多部分数据可以“大”并且它会咀嚼内存。
但是,经过这么说之后,有一项工作根本不安全,事实上要说。通过禁用'django.middleware.csrf.CsrfViewMiddleware',可以实现它。
从process_request或process_view访问middleware内的request.POST将阻止在中间件之后运行的任何视图能够修改请求的上传处理程序,并且通常应该避免。 CsrfViewMiddleware类可以被视为异常,因为它提供了csrf_exempt()和csrf_protect()装饰器,允许视图明确控制CSRF验证应在何时发生。
答案 3 :(得分:0)
如果目标是保存表单以便以后重新执行,则可以使用:
form.save(commit=False)
无需再保存request.Post