web-dev-qa-db-ja.com

django-なぜrequest.POSTオブジェクトは不変ですか?

タイトルが尋ねるように、なぜDjango guysはquerydictでrequest.POSTオブジェクトを実装することを決定しました(もちろん、これは全体を不変にしますか?)

投稿データのコピーを作成することでmutifyできることを知っています

post = request.POST.copy()

しかし、なぜこれを行うのですか?とにかく物を変更可能にするだけの方が簡単でしょうか?または、問題を引き起こす可能性のある他の理由でも使用されていますか?

106
bharal

ちょっとした謎ですね。いくつかの表面的にもっともらしい理論が調査で間違っていることが判明しました。

  1. POSTオブジェクトがミューテーションメソッドを実装する必要がないように?いいえ:POSTオブジェクトは Django.http.QueryDictクラス に属し、__setitem____delitem__popおよびclear。突然変異メソッドの1つを呼び出すときにフラグをチェックすることにより、不変性を実装します。 copyメソッドを呼び出すと、可変フラグがオンになっている別のQueryDictインスタンスが取得されます。

  2. パフォーマンスの改善のために?いいえ:可変フラグがオフの場合、QueryDictクラスはパフォーマンス上の利点を得ません。

  3. POSTオブジェクトを辞書キーとして使用できるように?いいえ:QueryDictオブジェクトはハッシュ可能ではありません。

  4. POSTデータを(応答全体の読み取りをコミットせずに)遅延的に構築できるように、 ここで主張されているように ?私はコードでこれの証拠を見ません:私が知る限り、応答の全体は常に、 直接 、または MultiPartParser 経由で読み込まれます= multipart応答用。

  5. プログラミングエラーからあなたを守るために?私はこれが主張されているのを見ましたが、これらのエラーが何であるか、そして不変性がそれらからどのように保護するかについての良い説明を見たことはありません。

いずれの場合も、POST常に不変ではありません:応答がmultipartの場合、POSTは可変です。これは、あなたが考えるかもしれないほとんどの理論にキボッシュを置くようです。 (この動作が見落としでない限り。)

要約すると、明確な根拠がわかりませんDjango POSTオブジェクトが不変であることmultipart以外のリクエストの場合。

128
Gareth Rees

リクエストがDjangoform送信の結果である場合、 POST beingimmutable)データの整合性を確保する between形式submissionおよび形式validation。ただし、リクエストがnotでDjangoform提出、次にPOST ismutableフォーム検証がないため。

いつでも次のようなことができます:( @ leo-the-manic's comment

#  .....
mutable = request.POST._mutable
request.POST._mutable = True
request.POST['some_data'] = 'test data'
request.POST._mutable = mutable
# ......
79
un33k

更新

Gareth Reesは、この場合、ポイント1と3が無効であると言っていました。ポイント2と4はまだ有効だと思いますが、ここでこれらを残します。

(Pyramid(Pylon)とDjangoの両方のrequest.POSTオブジェクトがMultiDictの何らかの形であることに気付きました。 request.POSTを不変にするよりも練習します。)


Django guysについて話すことはできませんが、これらの理由のいくつかのためにそれができるように思えますが:

  1. パフォーマンス。不変オブジェクトは、実質的な最適化を可能にするという点で、可変オブジェクトよりも「高速」です。オブジェクトが不変であるということは、作成時にオブジェクトにスペースを割り当てることができ、スペース要件が変わらないことを意味します。また、コピー効率や比較効率などの理由もあります。 編集:Gareth Reesが指摘したように、これはQueryDictには当てはまりません。
  2. request.POSTの場合、サーバー側のアクティビティはrequest'sデータを変更する必要がないようです。したがって、不変オブジェクトは、パフォーマンスに大きな利点があることは言うまでもなく、より適しています。
  3. 不変オブジェクトはdictキーとして使用できます。これは、Djangoのどこかで非常に便利ですsuppose 編集:私の間違い、immutableは直接hashableを意味しません;ただし、hashableオブジェクトは、通常immutableでもあります。
  4. request.POST(特にサードパーティのプラグインに)を渡すと、ユーザーからのこのリクエストオブジェクトは変更されないままであると期待できます。

何らかの意味で、これらの理由は「不変vs可変」に対する一般的な答えでもあります。質問。 Djangoの場合、上記よりもはるかに多くの設計上の考慮事項があります。

5
K Z

デフォルトでは不変であることが好きです。指摘したように、必要に応じて変更可能にすることができますが、明示的にする必要があります。 「フォームのデバッグを悪夢にすることはできるが、今何をしているのかは知っている」というようなものです。

4
pawelmech

Stack Answerのコメントでこれを見つけました https://stackoverflow.com/a/233996

そして、それは遅延なく構築できるように不変でなければなりません。コピーは、すべてのPOSTデータを強制的に取得します。コピーまでは、すべてがフェッチされるとは限りません。さらに、マルチスレッドWSGIサーバーが適切に機能するためには、これが不変

2
Seaux

注:multipartリクエストは、Django 1.11 https://github.com/Django/django/blob/stable/1.11.x/Django/ http/multipartparser.py#L292

以前のバージョンでは変更可能でした。

0
Alex Paramonov