django – 为什么request.POST对象是不可变的?
正如标题所要求的那样,为什么Django人决定用querydict实现request.POST对象(当然,这反过来又使得整个事物不可变?)
我知道你可以通过制作一份发布数据来复制它
post = request.POST.copy()
但为什么呢? 无论如何,只要让事情变得可变,肯定会更简单。 或者它也被用于其他一些可能导致问题的原因?
这有点神秘,不是吗? 几个表面上看似是而非的理论在调查中是错误的:
-
这样
POST
对象不必实现突变方法? No:POST
对象属于django.http.QueryDict
类 ,它实现了一套完整的突变方法,包括__setitem__
django.http.QueryDict
,django.http.QueryDict
,pop
和clear
。 当你调用一个突变方法时,它通过检查一个标志来实现不变性。 而当你调用copy
方法时,你会得到另一个QueryDict
实例的可变标志打开。 -
为了提高性能? 否:closures可变标志时,
QueryDict
类不会获得性能优势。 -
这样
POST
对象可以用作字典键? 否:QueryDict
对象不可散列。 -
这样,
POST
数据可以build立懒惰(没有承诺读取整个响应), 在这里声称 ? 在代码中我没有看到这样的证据:据我所知,整个响应总是直接读取,或通过MultiPartParser
读取multipart
响应。 -
为了防止编程错误? 我已经看到这个声明,但是我从来没有看到这些错误是什么的一个很好的解释,以及不变性如何保护你。
在任何情况下, POST
并不总是不可变的 :当响应是multipart
, POST
是可变的。 这似乎把基布斯放在你可能想到的大多数理论上。 (除非这种行为是疏忽)
总之,在Django中, 我看不到任何明确的理由 ,因为POST
对象对于非multipart
请求是不可变的。
如果请求是Django form
提交的结果,那么POST是immutable
以确保表单提交和表单validation 之间的数据完整性。 但是,如果请求不是通过Django form
提交发送的,那么POST是mutable
因为没有表单validation。
你总是可以这样做:(根据@ leo-the-manic的评论 )
# ..... mutable = request.POST._mutable request.POST._mutable = True request.POST['some_data'] = 'test data' request.POST._mutable = mutable # ......
更新 :
Gareth Rees是对的,在这种情况下,1和3是无效的。 虽然我认为第二点和第四点仍然有效,所以我将在这里留下这些论点。
(我注意到Pyramid(Pylon)和Django的request.POST
对象都是MultiDict
一种forms,所以也许这是比request.POST
更普遍的做法, MultiDict
不可改变。)
我不能代表Django的人,尽pipe在我看来,这可能是由于以下原因:
-
性能 。不可变对象比可变对象“更快”,因为它们允许大量的优化。一个对象是不可变的,意味着我们可以在创build时为它分配空间,空间需求不会改变。因为它也有复制效率和比较效率的东西。编辑 :如Gareth里斯指出,这不是QueryDict
的情况。 - 在
request.POST
的情况下,似乎在服务器端没有活动需要改变请求的数据。 因此,不变的对象更适合,更不用说它们具有实质性的优势。 -
不可变的对象可以用作编辑 :我的错误, 不可变的不直接暗示可散列 ; 但是可哈希对象通常也是不可变的 。dict
键,我猜可能在Django某处非常有用。 - 当你传递
request.POST
(尤其是第三方插件)时,你可以期望这个来自用户的请求对象将保持不变。
在某些方面,这些原因也是对“不可变与可变”的通用答案。 题。 我确信在Django案例中有更多的devise考虑。
我发现这在评论堆栈回答https://stackoverflow.com/a/2339963
它必须是不可改变的,以便它可以懒散地build造。 复制力量获取所有POST数据。 直到副本,它可能不会被全部取出。 而且,对于一个multithreading的WSGI服务器来说,如果这个工作是不可变的,那么这个服务器将会很有帮助
我喜欢它默认是不可变的。 正如你所指出的那样,如果你需要,你可以使它变得可变,但是你必须明确它。 这就像'我知道我可以让我的formsdebugging噩梦,但我知道我现在在做什么。