request.POSTの挙動

  • June 28, 2007 07:00

いろいろ書こうと思ったのですが、結果から言えばドキュメントが一番分かりやすいです。 http://michilu.com/django/doc-ja/request_response/#querydict

とは言えせっかく書いたので一応。。。

Djangoのrequest.POSTはdjango.http.QueryDictオブジェクトのインスタンスです。 QuersyDictオブジェクトはdjango.utils.datastructures.MultiValueDictを継承してます。 ではMultiValueDictは何かというとpythonの辞書型を継承してます。

通常のPythonの辞書はkeyとvalueが一対一ですが、MultiValueDictは名前の通りkeyに対し複数のvalueを持ちます。 持ち方としては内部で配列で持ち、値を返すときに一番最後の配列の要素を返すようになっています。

ソースdjango/utils/datastructures.py

class MultiValueDict(dict):
        #((中略))
    def __getitem__(self, key): #__getitem__は dic["key"]などのように呼ばれたときに呼ばれる返す特殊メソッド
        """
        Returns the last data value for this key, or [] if it's an empty list;
        raises KeyError if not found.
        """
        try:
            list_ = dict.__getitem__(self, key) #keyに対応する配列を返す
        except KeyError:
            raise MultiValueDictKeyError, "Key %r not found in %r" % (key, self)
        try:
            return list_[-1] #配列の一番最後を返す
        except IndexError:
            return []

        #((後略))
In [25]: from django.utils.datastructures import MultiValueDict
In [26]: dic = MultiValueDict()
In [27]: dic.setlist("a",["A", "AA", "AAA"])
In [28]: dic.setlist("b", ["B"])
In [29]: dic["a"]
Out[29]: 'AAA'

In [30]: dic["b"]
Out[30]: 'B'

In [31]: dic.getlist("a")
Out[31]: ['A', 'AA', 'AAA']

In [32]: dic.lists()
Out[32]: [('a', ['A', 'AA', 'AAA']), ('b', ['B'])]

ということで、djangoはPOSTもGETもパラメーターの順番を守ったまま値を入れるので(cgi.parse_qslがそういうものなので)request.POST["text"]で一番最後に入力された値が取得できます。

全ての値が必要な場合は request.POST.getlist("text")で入力された順に値が入った配列が取得します。

ちなみにQueryDictはインスタンスを作ったときに入れた値を変更するとエラーになるように拡張したMultiValueDictです。 request.POSTで得たデータを変更したデータを使う場合にrequest.POST.copy()をしなくてはこのためです。