django - 为什么request.POST对象是不可变的?

时间:2012-09-26 22:21:20

标签: django post

正如标题所示,为什么Django家伙决定使用querydict实现request.POST对象(当然,这反过来会使整个事情变得不可变?)

我知道你可以通过复制帖子数据来 mutify

post = request.POST.copy()

但为什么这样呢?当然,只要让事情变得可变就更简单了?或者它是否也被用于其他可能导致问题的原因?

6 个答案:

答案 0 :(得分:127)

这有点神秘,不是吗?一些表面上看似合理的理论在调查中证明是错误的:

  1. 这样POST对象不必实现变异方法?否:POST对象属于django.http.QueryDict class,它实现了一整套变异方法,包括__setitem____delitem__popclear 。它通过在调用其中一种变异方法时检查标志来实现不变性。当你调用copy方法时,你会得到另一个QueryDict实例,并打开了可变标志。

  2. 为了提高绩效?否:当关闭可变标志时,QueryDict类不会获得性能优势。

  3. 这样POST对象可以用作字典键吗?否:QueryDict对象不可清除。

  4. 这样可以懒惰地构建POST数据(不承诺阅读整个响应),as claimed here?我在代码中没有看到这方面的证据:据我所知,整个响应总是被读取,directlyMultiPartParser multipart响应。

  5. 为了保护您免受编程错误的影响?我已经看到了这个说法,但我从来没有看到这些错误是什么的好解释,以及不变性如何保护你免受它们的侵害。

  6. 在任何情况下,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的人说话,虽然在我看来它可能是因为其中一些原因:

  1. 性能。不可变对象更快&#34;在可变的,他们允许实质性的优化。对象是不可变的意味着我们可以在创建时为其分配空间,并且空间要求不会改变。它还具有复制效率和比较效率等特点。 修改:Gareth Rees指出,QueryDict不是这种情况。
  2. request.POST的情况下,似乎服务器端的任何活动都不需要更改请求的数据。因此,不可变对象更适合,更不用说它们具有很大的性能优势。
  3. 不可变对象可以用作dict键,我假设在Django的某个地方非常有用.. 修改:我的错误,不可变并不直接暗示 hashable ; hashable 对象通常也是 immutable
  4. 当您传递request.POST(特别是第三方插件和传出)时,您可以预期用户的此请求对象将保持不变。
  5. 从某些方面来说,这些原因也是&#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

在以前的版本中它们是可变的。