前回ラジオボタンの例を説明しましたが、
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」とか書いたりする必要はありません。