## 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").upper()

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

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

ここで述べる高水準のインタフェースで提供している `getfirst()` や `getlist()` メソッドを使うと、もっと便利にアプローチできます。

`getfirst`( | name[, default])

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

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

`getlist`( | name)

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

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

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

#### Footnotes

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