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

django-为什么request.POST对象是不可变的?,django,post,Django,Post,正如标题所问,为什么Django人决定用querydict实现request.POST对象(当然,这反过来又使整个事情不可变?) 我知道你可以通过复制一份post数据来破坏它 post = request.POST.copy() 但为什么要这样做呢?不管怎样,允许事物是可变的肯定会更简单?或者它也被用于其他可能导致问题的原因?更新: Gareth Rees认为第1点和第3点在本案中无效是正确的。虽然我认为第2点和第4点仍然有效,因此我将把论文留在这里 (我注意到Pyramid(Pylon)和D

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

我知道你可以通过复制一份post数据来破坏它

post = request.POST.copy()

但为什么要这样做呢?不管怎样,允许事物是可变的肯定会更简单?或者它也被用于其他可能导致问题的原因?

更新

Gareth Rees认为第1点和第3点在本案中无效是正确的。虽然我认为第2点和第4点仍然有效,因此我将把论文留在这里

(我注意到Pyramid(Pylon)和Django的
request.POST
对象都是某种形式的
MultiDict
。因此,这可能比使
request.POST
不可变更常见。)


我不能代表Django的人说话,尽管在我看来可能是因为以下原因:

  • 性能。不可变对象比可变对象“更快”,因为它们允许大量优化。对象是不可变的,这意味着我们可以在创建时为其分配空间,并且空间需求不会改变。因为它还具有复制效率和比较效率。 编辑:正如Gareth Rees指出的那样,
    QueryDict
    的情况并非如此
  • request.POST
    的情况下,似乎服务器端的任何活动都不需要更改请求的数据。因此,不可变对象更适合,更不用说它们具有显著的性能优势
  • 不可变对象可以用作
    dict
    键,我想这在Django的某些地方可能非常有用。。 编辑:我的错误,不可变并不直接意味着可散列;然而,散列对象通常也是不可变的
  • 当您传递
    request.POST
    (尤其是传递给第三方插件和out)时,您可以预期来自用户的此请求对象将保持不变

  • 在某种程度上,这些原因也是对“不变与可变”问题的一般回答。我敢肯定,在Django的案例中,有比上述更多的设计考虑。

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

  • 这样
    POST
    对象就不必实现变异方法了?否:
    POST
    对象属于,它实现了一整套变异方法,包括
    \uuuuu setitem\uuuuuuuu
    \uuuuuu delitem\uuuuu
    pop
    清除
    。它通过在调用其中一个变异方法时检查标志来实现不变性。当您调用
    copy
    方法时,您会得到另一个
    QueryDict
    实例,并且启用了可变标志

  • 为了提高性能?否:
    QueryDict
    类在禁用可变标志时不会获得性能优势

  • 以便
    POST
    对象可以用作字典键?否:
    QueryDict
    对象不可散列

  • 这样就可以懒洋洋地构建
    POST
    数据(无需提交读取整个响应)?我在代码中看不到这方面的证据:据我所知,整个响应都是读取的,或者是通过
    多部分
    响应读取的

  • 为了防止编程错误?我看到过这种说法,但我从来没有看到过关于这些错误是什么以及不变性如何保护您免受这些错误影响的好解释

  • 在任何情况下,
    POST
    并不总是不变的:当响应是
    multipart
    时,
    POST
    是可变的。这似乎使你可能想到的大多数理论都大错特错。(除非这种行为是疏忽。)


    总之,我在Django中看不到
    POST
    对象对于非
    多部分
    请求不可变的明确理由。

    如果请求是Django
    表单提交的结果,然后,POST是不可变的,以确保提交表单和验证表单之间数据的完整性。但是,如果请求不是通过Django
    表单提交的,则POST是可更改的,因为没有表单验证

    你总是可以这样做的:(根据)


    我在Stack Answer的评论中发现了这一点

    而且它必须是不可变的,这样才能懒散地构建它。复制强制获取所有POST数据。在复制之前,可能无法获取所有副本。此外,对于多线程WSGI服务器来说,如果它是不可变的,那么它将非常有用


    我喜欢它在默认情况下是不可变的。 如前所述,如果需要,您可以使其可变,但必须明确说明。
    这就像“我知道我可以让表单调试成为一场噩梦,但我知道我现在在做什么。”

    请注意:
    多部分请求自Django 1.11以来是不可变的
    


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

    为什么您希望它是可变的?您可以从中获取数据,并在视图中使用/修改它。通过向其中添加数据,您可能会给人一种印象,即
    request.POST
    提交的数据比实际提交的数据多。我并不希望它是可变的。不超过,比方说,我想要冰激凌变凉。但就冰淇淋而言,如果它不冷,它就会融化,然后你会因为弄得一团糟而被责骂。但是对于request.POST对象。。。我的意思是,如果我要把我的代码搞砸,我会把它搞砸的。我不知道开发人员向POST对象添加数据并导致问题的流行
    #  .....
    mutable = request.POST._mutable
    request.POST._mutable = True
    request.POST['some_data'] = 'test data'
    request.POST._mutable = mutable
    # ......