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


109

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

私はあなたが投稿データのコピーを作成することによってそれを変形できることを知っています

post = request.POST.copy()

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


1
なぜ変更可能にしたいですか?それからデータを取得し、ビューで使用/変更できます。データを追加することにより、request.POST実際よりも多くのデータを使用して送信されたインプレッションを作成できます。
Simeon Visser 2012

11
変更可能にしたいわけではありません。アイスクリームは冷たくしたいだけです。アイスクリームの場合は、しかし、それは場合ではない寒さ、それが溶融し、その後、あなたは大きな老いた混乱を作るために叱ら。しかし、request.POSTオブジェクトを使用すると...つまり、コードを台無しにする場合は、台無しにします。開発者がPOSTオブジェクトにデータを追加したり、問題を引き起こしたりする風土があることを知りませんでした。
bharal 2012

いい質問です。本当に考えたことはありません。
Burhan Khalid 2012

1
クライアントがJSONデータ(可変)とURLフォームエンコード(不変)メッセージを送信することがあったため、これは散発的に発生しました。
owenfi 2015年

2
英語を母国語としない人にとって、「mutify」は単語ではありません-正しいフレーズは「you can mutate it it」または「you can modify it」です。また、開発者を性別で区別する必要もありません。「みんな」ではなく「Django team」または「core devs」を使用できます。
alexmuller 2017年

回答:


131

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

  1. だからPOSTオブジェクトは、突然変異のメソッドを実装する必要はありませんか?いいえ:POSTオブジェクトはクラスに属していますdjango.http.QueryDictを含む変異メソッドのフルセットを実装して、__setitem____delitem__popclear。ミューテーションメソッドの1つを呼び出すときにフラグをチェックすることにより、不変性を実装します。また、copyメソッドを呼び出すQueryDictと、変更可能なフラグがオンになっている別のインスタンスが取得されます。

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

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

  4. だからPOSTデータは、(全体の応答を読み取るためにコミットせず)レイジーに構築することができ、ここで記載の?コードにこれの証拠はありません。私が知る限り、応答全体も常に読み取られます。直接、または応答経由MultiPartParserでれmultipartます。

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

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

要約すると、Djangoでは、オブジェクトがリクエスト以外に対して不変であるという明確な根拠はありませんPOSTmultipart


私はDjangoでこのようなラフなエッジがたくさんあることに気づきました。しかし、ある時点で誰かにとって意味があったに違いありません。
Dan Passaro、2014年

2
私はこれを別のスタックの答えで見つけました:「そしてそれは遅延して構築できるように不変でなければなりません。コピーはすべてのPOSTデータを強制的に取得します。コピーまで、すべてがフェッチされない可能性があります。さらに、マルチスレッドWSGIの場合サーバーは適切に機能するため、これが不変である場合に役立ちます。」
Seaux

12
@Seauxは、コメントするつもりでSOの回答をゆっくりと読むべきではありません。;-)
Chris Wesseling

3
@ChrisWesseling私はあなたがそこで何をしたかを見ます
Seaux

2
さらに良いことに、djangoテストクライアントを使用してリクエストを送信すると、querydictは変更可能です。
user1158559 2017年

82

リクエストがDjangoのの結果であった場合にform提出、POSTがあることのため合理的であるimmutableデータの整合性を確認するために間にフォームの提出とフォームのバリデーションを。ただし、リクエストがDjango送信を介して送信されなかった場合、formPOSTはmutableフォーム検証がないためです。

あなたはいつでもこのようなことをすることができます:(@ leo-the-manicのコメントに従って)

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

3
@JoshK:コメント投稿者がPOSTを変更可能にしたかったので、この回答のコードスニペットが役に立ちました。
ShreevatsaR 2015年

新しいキー、値を追加できますが、既存のデータを変更することはできません。
Vamsidhar Muggulla 2017年

いいね。そして、私はこのコードを使用する誰もが彼または彼女が何をしているか知っていると確信しています。
John Pang

@VamsidharMuggulla追加と変更の両方が可能です。削除も可能です。
アントニーハッチキンス

5

更新

この場合、ポイント1と3は無効であるとGareth Reesは正しかった。ポイント2と4はまだ有効だと思いますが、ここではここに残しておきます。

(私はrequest.POSTPyramid(Pylon)とDjangoの両方のオブジェクトが何らかの形式であることに気づきましたMultiDict。ですから、おそらくそれをrequest.POST不変にするよりも一般的な方法です。)


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

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

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


1
最後のケースは本当に重要です。それは本当にセキュリティについてです。これが、Django sessionsが状態間でデータを取得および変更するための短期間の方法を提供する理由です。
CppLearner 2012

2
POSTQueryDictオブジェクトであり、これらのオブジェクトは不変であることによるパフォーマンス上のメリットがないため、この場合、あなたのポイント(1)は答えにはなりません。そして、あなたのポイント(3)は答えにQueryDictはなりません。オブジェクトはハッシュ可能ではないので、辞書キーとして使用できないからです。
Gareth Rees、2012

@GarethReesこれらを指摘していただきありがとうございます。確かに私は間違っていました。これらを修正するために回答を更新しました。QueryDict返事をする前にもっと注意を向けるべきだった。
KZ

7
@CppLearnerたとえば、セキュリティポイントは意味がないようですrequests.POST._mutable = True; requests.POST['foo'] = 'bar'; request.POST._mutable = False
Dan

4

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


2

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

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


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.