先頭には "import cgi" と書いてください。"from cgi import *"と書いてはいけません -- このモジュールは以前のバージョンとの互換性を 持たせるために内部で呼び出す名前を多数定義しており、それらが ユーザの名前空間に存在する必要はありません。
新たにスクリプトを書く際には、以下の一行を付加するかどうか検討してください:
import cgitb; cgitb.enable()
これによって、特別な例外処理が有効にされ、エラーが発生した際にブラウザ 上に詳細なレポートを出力するようになります。ユーザにスクリプトの内部を 見せたくないのなら、以下のようにしてレポートをファイルに保存できます:
import cgitb; cgitb.enable(display=0, logdir="/tmp")
スクリプトを開発する際には、この機能はとても役に立ちます。
cgitb が生成する報告はバグを追跡するためにかかる
時間を大きく減らせるような情報を提供してくれます。スクリプトを
テストし終わり、正確に動作することを確認した後はいつでも
cgitb
の行を削除できます。
入力されたフォームデータを取得するには、 FieldStorage クラス を使うのが最良の方法です。このモジュールで定義されている他のクラスの ほとんどは以前のバージョンとの互換性のためのものです。 インスタンス生成は引数なしで必ず 1 度だけ行います。これにより、 標準入力または環境変数からフォームの内容が読み出されます (どちらから読み出されるかは、CGI 標準に従って設定されている 複数の環境変数の値によって決められます)。インスタンスが標準入力を 使うかもしれないので、インスタンス生成を行うのは一度だけにしなければ なりません。
FieldStorage のインスタンスは Python の辞書のようにインデクス を使った参照ができ、標準の辞書に対するメソッド has_key() と keys() をサポートしています。組み込みの関数 len() もサポートされています。空の文字列を含むフォームのフィールドは 無視され、辞書上にはありません; そういった値を保持するには、 FieldStorage のインスタンスを生成する時にオプションの keep_blank_values キーワード引数を true に設定してください。
例えば、以下のコード (Content-Type: ヘッダと空行は
すでに出力された後とします) は name
および addr
フィールドが両方とも空の文字列に設定されていないか調べます:
form = cgi.FieldStorage() if not (form.has_key("name") and form.has_key("addr")): print "<H1>Error</H1>" print "Please fill in the name and addr fields." return print "<p>name:", form["name"].value print "<p>addr:", form["addr"].value ...further form processing here...
ここで、"form[key]" で参照される各フィールドは それ自体が FieldStorage (または MiniFieldStorage 。 フォームのエンコードによって変わります) のインスタンスです。 インスタンスの属性 value フィールドの文字列値になります。 getvalue() メソッドはこの文字列値を直接返します。 getvalue() は 2 つめの引数にオプションの値を与えることが でき、リクエストされたキーが存在しない場合に返されるデフォルトの 値になります。
入力されたフォームデータに同じ名前のフィールドが二つ以上あれば、 "form[key]" で得られるオブジェクトは FieldStorage や MiniFieldStorage のインスタンスではなく、それらインスタンスから なるリストになります。同じく、この状況では、 "form.getvalue(key)" は文字列を要素とするリストを返します。 もしこうした状況が起こりうると思われるなら (HTML のフォームに同じ名前をもったフィールドが複数含まれているのなら) 、 組み込み関数 getlist() を使ってください。この関数は 常に値のリストを返します (従って、要素が単一の場合を特別扱い しなくて済みます)。 例えば、以下のコードは任意の数のユーザ名フィールドを 結合し、コンマで分割された文字列にします:
value = form.getlist("username", "") usernames = ",".join(value)
フィールドがアップロードされたファイルを表す場合、value 属性または getvalue() メソッドを介してアクセスされた 値はファイルの内容を全て文字列としてメモリ上に読み込みます。 これは望ましくない機能かもしれません。アップロードされたファイルが あるかどうかは filename 属性および file 属性の いずれかで調べることができます。その後、以下のようにして file 属性から落ち着いてデータを読み出せます:
fileitem = form["userfile"] if fileitem.file: # It's an uploaded file; count lines linecount = 0 while 1: line = fileitem.file.readline() if not line: break linecount = linecount + 1
現在ドラフトとなっているファイルアップロードの標準仕様では、一つの フィールドから (再帰的な multipart/* エンコーディングを 使うことで) 複数のファイルがアップロードされる可能性を受け入れています。 この場合、アイテムは辞書形式の FieldStorage アイテムと なります。複数ファイルかどうかは type 属性が multipart/form-data (または multipart/* に マッチする他の MIME 型) になっているかどうか調べることで判別できます。 この場合、トップレベルのフォームオブジェクトと同様にして再帰的に 個別処理できます。
フォームが ``古い'' 形式で入力された場合 (クエリ文字列または
application/x-www-form-urlencoded データの単一の部分の場合)
アイテムは実際には MiniFieldStorage クラスのインスタンス
になります。この場合、list 、file 、および
filename 属性は常に None
になります。
ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。