正如标题所示,为什么Django家伙决定使用querydict实现request.POST对象(当然,这反过来会使整个事情变得不可变?)
我知道你可以通过复制帖子数据来 mutify
post = request.POST.copy()
但为什么这样呢?当然,只要让事情变得可变就更简单了?或者它是否也被用于其他可能导致问题的原因?
答案 0 :(得分:127)
这有点神秘,不是吗?一些表面上看似合理的理论在调查中证明是错误的:
这样POST
对象不必实现变异方法?否:POST
对象属于django.http.QueryDict
class,它实现了一整套变异方法,包括__setitem__
,__delitem__
,pop
和clear
。它通过在调用其中一种变异方法时检查标志来实现不变性。当你调用copy
方法时,你会得到另一个QueryDict
实例,并打开了可变标志。
为了提高绩效?否:当关闭可变标志时,QueryDict
类不会获得性能优势。
这样POST
对象可以用作字典键吗?否:QueryDict
对象不可清除。
这样可以懒惰地构建POST
数据(不承诺阅读整个响应),as claimed here?我在代码中没有看到这方面的证据:据我所知,整个响应总是被读取,directly或MultiPartParser
multipart
响应。
为了保护您免受编程错误的影响?我已经看到了这个说法,但我从来没有看到这些错误是什么的好解释,以及不变性如何保护你免受它们的侵害。
在任何情况下,POST
并非总是不可变:当回复为multipart
时,POST
是可变的。这似乎把你可能想到的大多数理论都放在了一边。 (除非这种行为是疏忽。)
总之,我在Django中看不到明确的理由,因为POST
对象对于非multipart
请求是不可变的。
答案 1 :(得分:79)
如果请求是Django form
提交的结果,那么POST immutable
以确保完整性是合理的数据 表单提交和表单验证。但是,如果请求是通过Django form
提交 发送的,则POST为 mutable
,因为没有表格验证。
您可以随时执行以下操作:(根据@leo-the-manic's comment)
# .....
mutable = request.POST._mutable
request.POST._mutable = True
request.POST['some_data'] = 'test data'
request.POST._mutable = mutable
# ......
答案 2 :(得分:5)
<强>更新强>:
Gareth Rees是正确的第1点&amp;在这种情况下,3无效。虽然我认为第2点和第4点仍然有效,但我会留下这些论文。
(我注意到金字塔(Pylon)和Django的request.POST
对象都是某种形式的MultiDict
。所以也许这种做法比制作request.POST
更常见。不可变的。)
我不能代表Django的人说话,虽然在我看来它可能是因为其中一些原因:
QueryDict
不是这种情况。 request.POST
的情况下,似乎服务器端的任何活动都不需要更改请求的数据。因此,不可变对象更适合,更不用说它们具有很大的性能优势。dict
键,我假设在Django的某个地方非常有用.. request.POST
(特别是第三方插件和传出)时,您可以预期用户的此请求对象将保持不变。从某些方面来说,这些原因也是&#34;不可变与可变的一般答案?&#34;题。我确信在Django案例中有更多的设计考虑因素。
答案 3 :(得分:3)
我喜欢它默认是不可变的。 正如所指出的那样,如果你需要,你可以使它变得可变,但你必须明确它。 它就像是我知道我可以让我的表单调试噩梦,但我知道我现在在做什么。&#39;
答案 4 :(得分:2)
我在Stack Answer https://stackoverflow.com/a/2339963
的评论中发现了这一点它必须是不可变的,以便它可以懒惰地构建。复制强制获取所有POST数据。直到副本,它可能不会全部被提取。此外,为了使多线程WSGI服务器能够很好地工作,如果这是不可变的,它会很有用
答案 5 :(得分:0)
请注意:自Django 1.11起,multipart
请求是不可变的
https://github.com/django/django/blob/stable/1.11.x/django/http/multipartparser.py#L292
在以前的版本中它们是可变的。