就像标题所问的那样,为什么Django伙计们决定通过querydict来实现request.POST对象(当然,这又使整个事情变得不可变了?)
我知道您可以通过复制帖子数据来对其进行更改
post = request.POST.copy()
但是为什么呢?当然,仅允许事物变得易变会更简单吗?还是由于其他原因使用它而可能导致问题?
就像标题所问的那样,为什么Django伙计们决定通过querydict来实现request.POST对象(当然,这又使整个事情变得不可变了?)
我知道您可以通过复制帖子数据来对其进行更改
post = request.POST.copy()
但是为什么呢?当然,仅允许事物变得易变会更简单吗?还是由于其他原因使用它而可能导致问题?
Answers:
这是一个谜,不是吗?在调查中,一些表面上似乎合理的理论是错误的:
这样POST
对象就不必实现变异方法了吗?编号:该POST
对象所属的django.http.QueryDict
类,它实现了全套的突变方法,包括__setitem__
,__delitem__
,pop
和clear
。当您调用一种变异方法时,它通过检查一个标志来实现不变性。当您调用该copy
方法时,您将获得另一个QueryDict
实例,该实例的mutable标志处于打开状态。
为了提高性能?否:QueryDict
关闭可变标志后,该类不会获得任何性能优势。
这样该POST
对象可以用作字典键?否:QueryDict
对象不可散列。
这样POST
就可以懒惰地构建数据(无需提交读取整个响应),如此处所述?我没有看到这方面的证据代码:据我所知,整个反应总是读,无论是直接或通过MultiPartParser
对multipart
反应。
为了保护您免受编程错误的侵害?我已经看到了这种说法,但是从未见过对这些错误是什么以及不变性如何保护您免受错误的很好的解释。
无论如何,POST
它并不总是不变的:当响应为时multipart
,则POST
是可变的。这似乎使大多数人可能想到的理论陷入困境。(除非这种行为是疏忽。)
总之,在Django中,我看不出有明确的理由可以使POST
对象对于非multipart
请求是不可变的。
如果请求是Django form
提交的结果,则POST合理的做法是immutable
确保表单提交和表单验证之间的数据完整性。但是,如果该请求不是通过Django 提交发送的,则POST是因为没有表单验证。form
mutable
您可以随时执行以下操作:(按照@ 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点在这种情况下无效。尽管我认为第2点和第4点仍然有效,所以我将把这些留在这里。
(我注意到request.POST
Pyramid(Pylon)和Django 的对象都是某种形式MultiDict
。因此,也许比使request.POST
不可变更普遍。)
我无法代表Django员工发言,尽管在我看来这可能是由于以下一些原因:
QueryDict
正如Gareth Rees所指出的,情况并非如此。request.POST
,似乎服务器端没有任何活动需要更改请求的数据。因此,不可变对象更适合,更不用说它们具有实质性的性能优势。dict
键,我想这在Django中可能非常有用。request.POST
(尤其是传递给第三方插件)时,您可以期望来自用户的此请求对象将保持不变。从某种程度上说,这些原因也是“不变与可变?”的通用答案。题。我敢肯定,在Django案例中,还有比以上更多的设计注意事项。
sessions
一种在状态之间获取和修改数据的短期方法。
POST
是一个QueryDict
object,并且这些对象由于不可变而没有任何性能优势。而且,您的观点(3)不能解决问题,因为QueryDict
对象不可哈希,因此不能用作字典键。
QueryDict
在回答之前,我应该更加注意。
requests.POST._mutable = True; requests.POST['foo'] = 'bar'; request.POST._mutable = False
我在Stack Answer https://stackoverflow.com/a/2339963的评论中找到了这个
而且它必须是不可变的,以便可以延迟构建。复制会强制获取所有POST数据。在复制之前,可能无法全部获取。此外,为了使多线程WSGI服务器正常运行,如果这是不可变的,则将很有帮助
请注意:multipart
自Django 1.11开始,请求是不变的
https://github.com/django/django/blob/stable/1.11.x/django/http/multipartparser.py#L292
它们在以前的版本中是可变的。
request.POST
已提交的印象,其中包含的数据比实际要多。