$3 ブラウザからのデータの取得

3-3 フォームからのデータ取得 その2

前回ラジオボタンの例を説明しましたが、 CGIの処理は例外を除いて他の場合でも同じです。 つまり、ページでラジオボタン、セレクトメニュー、テキストボックスのどれになっていても、 CGIへは「NAME=VALUE&NAME=VALUE&・・・」というふうに、 「NAME」と「VALUE」だけが送られるのです。
したがって、CGIでは「NAME」と「VALUE」の組み合わせだけで判断することになります。 言いかえれば、ページでラジオボタンだったのを、セレクトメニューやテキストボックスに置き換えても、 CGIプログラムは変える必要はありません。
(実際は、テキストボックスの場合は入ってくるデータが予測できないので、注意が必要です)

はじめに「例外を除いて」を書きましたが、その例外とは、チェックボックス、画像ボタン、 そしてファイルを直接送る場合です。ファイルを送る場合については説明しません。

画像ボタン(INPUT TYPE=image) の場合は、その画像のどの点がクリックされたのかが、 X座標、Y座標の数値のペアとして送られます。具体的には、
< INPUT TYPE=image SRC="button.gif" NAME="BUTTON" > というボタンに対して、例えば、
BUTTON.x=6&BUTTON.y=15 というデータが送られます。

チェックボックスでは、ひとつの項目について、複数のデータを送ることができます。 プログラムの立場で言えば「NAME=VALUE」という形式はそのままですが、 「Check=1&Check=3& ・・・」というように、 ひとつの「NAME」に対して、「VALUE」が複数になることもあります。 1個や0個の場合もあります。
(ラジオボタンとかでは、ひとつの「NAME」に対して、 ただ一つの「VALUE」だけが必ずきます)

Pythonの CGIライブラリでは、まず「Data = cgi.FieldStorage()」というオブジェクトを作り、 「Data['Key'].value」と、valueメソッドを使うことで、その値が得られました。
VALUE」が複数ある場合には、「Data['Key']」というオブジェクトはリストになります。 ここで注意するのは、「値のリスト」じゃなくて「その前の段階のオブジェクトのリスト」ということです。
具体的にそのリストの各要素の値を得るには「Data['Key'][1].value」というふうに、 「配列 Data['Key']の、1番目の要素(オブジェクト)に対して valueメソッドを使う」となります。

ただし、ここで大きな問題があります。 値がひとつしか選択されなかった場合は「Data['Key']」はリストでなく、 ラジオボタンとかと同じ一つのオブジェクトで、 前回と同じ方法になります。 さらに、値が選択されなかった場合、このときはエラーというか例外が発生しますので、その対応が別に必要です。
つまり、Pythonでは「値が無し」「値がひとつ」「値が複数」の、 3種類の場合の処理を用意する必要があります
しかし、この3種類の区別は、実際には値の個数で決めることはできなさそうです。 まず、「値が無し」の場合は「KeyError」という例外が起きます。 「値がひとつ」「値が複数」の区別は、オブジェクト「Data['Key']」の型で調べます。 「値が複数」の時はリスト型になります。 「値がひとつ」の時は、簡単に○○型と言えませんが、「cgi.FieldStorage()」と同じ型になるということを利用します (この区別は、もっと簡単な方法があるかも知れませんが・・・)。

このことをふまえて、例をつくってみましょう。

  1: try:
  2:   if type(Data['Key']) == type(cgi.FieldStorage()):    #値がひとつの場合
  3:      print Data['Key'].value 
  4:  
  5:   elif type(Data['Key']) == type([]):    #値が複数の場合
  6:     for Item in Data['Key']:
  7:        print Item.value 
  8:        count = count + 1 
  9: 
 10: except KeyError:    #値が無い場合
 11:   print "何もありません" 

まず、1行目の「try:」のブロックが実行されます。 もし値が無いときには、ブロック内で例外(エラー)が起きて、 10行目の「except」のブロックが実行されます。 この例では「KeyError」という例外が発生する可能性があるので、 「except KeyError:」と書いて、そのあとに例外時のスクリプトを書きます。 例外が起きなければ、exceptブロックは実行されません (他の例外が起きる可能性があるときは、そのぶんの別の exceptブロックを用意しておきます)。

2行目は、値が一つの場合のチェックです。cgi.FieldStorage()と同じ型かどうかチェックします。
5行目は、値が複数の場合のチェックです。この時、Data['Key'] の型はリストになります。 「type([])」でリストの型が返されるので、これで比較できます (ちなみに、数値型は type(0)、文字型は type("") で比較できます)。 6行目から、複数の値に対しての繰り返しのブロックになります。

Pythonでは、行頭の空白(インデント)でブロックの判断をするので、 7行目、8行目のインデントは同じでなければいけません。 同様に、1行目と10行目、2行目と5行目のインデントも同じにします。 そのかわり、かっこ( ( ), { })で囲んだり、最後に「end」とか書いたりする必要はありません。


Next: 4-1 簡単なパズル

Previous: 3-2 フォームからのデータ取得 その1

Contents


Foundation of CGI Page

春風はるか haruka@harukaze.net