## 11.2.3 高レベルインタフェース

バージョン2.2 以降で新規追加された 仕様です。

前節では CGI フォームデータを `FieldStorage` クラスを使って 読み出す方法について解説しました。この節では、フォームデータを 分かりやすく直感的な方法で読み出せるようにするために追加された、より 高レベルのインタフェースについて記述します。 このインタフェースは前節で記述された技術を撤廃するものでは ありません -- 例えば、前節の技術は依然としてファイルのアップロードを 効率的に行う上で便利です。

このインタフェースは 2 つの単純なメソッドからなります。このメソッドを 使うことで、一般的な方法でフォームデータを処理でき、 一つのフィールド名に対して入力された値が一つなのかそれ以上なのか を心配する必要がなくなります。

前節では、一つのフィールド名に対して二つ以上の値が入力される かもしれない場合には、常に以下のようなコードを書くよう学びました:

    item = form.getvalue("item")
    if isinstance(item, list):
        # The user is requesting more than one item.
    else:
        # The user is requesting only one item.

こういった状況は、例えば以下のように、同じ名前を持った複数の チェックボックスからなるグループがフォームに含まれているような場合に よく起こります:

    <input type="checkbox" name="item" value="1" />
    <input type="checkbox" name="item" value="2" />

しかしながら、ほとんどの場合あるフォーム中で特定の名前を持った コントロールはただ一つなので、その名前に関連付けられた値は ただ一つしかないと期待され、かつ一つの値しか必要ありません。 そこで、スクリプトには例えば以下のようなコードを書くでしょう:

    user = form.getvalue("user").toupper()

このコードの問題点は、クライアント側がスクリプトに有効な入力 を提供すると期待できないところにあります。 例えば、もし好奇心旺盛なユーザがもう一つの "`user=foo`" ペア をクエリ文字列に追加したら、`getvalue(``'user')` メソッドを 呼び出したときに文字列ではなくリストが返されるため、このスクリプトは クラッシュするでしょう。 リストに対して `toupper()` メソッドを呼び出すと、引数が 有効でない (リスト型はその名前のメソッドを持っていない) ため、例外 `AttributeError` が送出されます。

従って、フォームデータの値を読む適切な方法は、得られた値が 単一の値なのか値のリストなのかを常に調べるコードを使うという ものでした。これでは煩わしく、また、より読みにくいスクリプトに なってしまいます。

より便利なアプローチは、ここで述べる高レベルのインタフェースが 提供する `getfirst()` および `getlist()` メソッドを 使うことです。

`getfirst`( | name[, default])

  フォームフィールド name に関連付けられた値をつねに一つだけ 返す軽量メソッドです。このメソッドは同じ名前で 1 つ以上の値が ポストされた場合、最初の値だけを返します。フォームから値を受信する 際の値が並べられる順番はブラウザ間で異なる可能性があり、特定の順番 であるとは期待できないので注意してください。 11.1

  指定したフォームフィールドや値がない場合、このメソッドはオプションの引数 default を返します。このパラメタを指定しない場合、標準の 値は `None` に設定されます。

`getlist`( | name)

  このメソッドはフォームフィールド name に関連付けられた値を 常にリストで返します。name に指定したフォームフィールドや値が 存在しない場合、このメソッドは空のリストを返します。値が一つだけ 存在する場合、要素を一つだけ含むリストを返します。

これらのメソッドを使うことで、以下のようにナイスでコンパクトな コードを書くことができます:

    import cgi
    form = cgi.FieldStorage()
    user = form.getfirst("user", "").toupper()    # This way it's safe.
    for item in form.getlist("item"):
        do_something(item)

... であるとは期待できないので注意してください。11.1
  最近のバージョンの HTML 仕様では、フィールドの値が提供される 順番を取り決めてはいますが、ある HTTP リクエストがその取り決めに 従ったブラウザから受信したのかどうか、そもそもブラウザから送信 されたのかどうかの判別は退屈で間違いやすいので注意してください。