python-cgiモジュールのFieldStorage型について

# はじめに
pythonでwebページ間でデータをやりとりする為に
**cgiモジュール**を使った際に
調べた**cgi.FieldStorage型**について整理しました。

>Pythonの公式ドキュメントはこちら
https://docs.python.org/3/library/cgi.html

>python-cgiについての記事はこちら
https://qiita.com/Taro_man/items/82fb537688e0f2be4915


# cgi.FieldStorage
cgiモジュールで使用されているクラス。
FieldStorageクラスをインスタンス化することで、
クライアントから送られる**フォームの内容を取得**できるようになる。

# 主な使い方
pythonファイルが実行された`<form></form>`に紐付く**htmlタグを取得**する。

例えば、以下のような記述を html と python に書いた場合、変数formの中身は次のようになる。

**変数form(FieldStorage型)**
`(None, None, [MiniFieldStorage('hdn_name', 'hdn_value1'), MiniFieldStorage('hdn_name', 'hdn_value2'), MiniFieldStorage('text_name', 'text_value'), MiniFieldStorage('button', 'submit!!')])`

```python
# Python
form = cgi.FieldStorage()
```

```html
<!-- HTML -->
<form name="formSubmit" action="cgibin.py">
  <input type="hidden" name="hdn_name" value="hdn_value1">
  <input type="hidden" name="hdn_name" value="hdn_value2">
  <input type="text" name="text_name" value="text_value">
  <input type="submit" name="button" value="submit!!">
</form>
```

# データの取り出し方
上記のhtml, cgi.FiledStorageインスタンスを例に
フォームのデータを取り出す方法を以下に記載します。

## 注釈
以降の説明では例の
name="hogename"に当たる部分を**html_name**, 
value="hogevalue"に当たる部分を**html_value** と表現します。

```html
<!-- (例) -->
<input type="hidden" name="hogename" value="hogevalue">
```


## form.getvalue(name)
指定したhtml_nameに紐付く、**全てのhtml_value**を返す。

紐付くhtml_nameが
1つの場合は**String型**、複数ある場合は**list型**で返す。

```python
# 例1)
# 変数名:格納されるデータ:型
# ret:'text_value':<class str>
ret = form.getvalue('text_name')
```

```python
# 例2)
# 変数名:格納されるデータ:型
# ret:['hdn_value1', 'hdn_value2']:<class list>
ret = form.getvalue('hdn_name')
```

上記の通り、
html_nameの数によって、返ってくる型が異なるので、**バグ懸念**があります。
個人的には、後述の**form.getlist()**を使った方が良いと思います。


## form.getlist(name)
指定したhtml_nameに紐付く、**全てのhtml_value**を返す。
紐付くhtml_nameの数に関わらず、**list型**で返す。

```python
# 例1)
# 変数名:格納されるデータ:型
# ret:['text_value']:<class list>
ret = form.getlist('text_name')
```

```python
# 例2)
# 変数名:格納されるデータ:型
# ret:['hdn_value1', 'hdn_value2']:<class list>
ret = form.getlist('hdn_name')
```

## form.list
pythonファイルが実行された`<form>`タグに紐付く、**html_nameとhtml_value**をlistで返す。
listの要素はMiniFieldStorage型。
**MiniFieldStorage型**は、辞書型のように(key, value)形式でデータを持つ。

```python
# 例)
# 変数名:格納されるデータ:型
# ret:[MiniFieldStorage('hdn_name', 'hdn_value1'), MiniFieldStorage('hdn_name', 'hdn_value2'), MiniFieldStorage('text_name', 'text_value'), MiniFieldStorage('button', 'submit!!')]:<class list>
ret = form.list
```

htmlタグを全部取ってきて
XXXというhtml_valueがあれば処理1、
YYYというhtml_valueがあれば処理2　というような**分岐処理**に使える。


## form[name]
指定したhtml_nameとそれに紐付くhtml_valueを**MiniFieldStorage型**で返す。
紐付くhtml_nameが複数ある場合、**list型 of MiniFieldStorage型**で返す。

```python
# 例1)
# 変数名:格納されるデータ:型
# ret:MiniFieldStorage('text_name', 'text_value'):<class MiniFieldStorage>
ret = form['text_name']
```

```python
# 例2)
# 変数名:格納されるデータ:型
# ret:[MiniFieldStorage('hdn_name', 'hdn_value1'), MiniFieldStorage('hdn_name', 'hdn_value2')]:<class list>
ret = form['hdn_name']
```

## form[name].value
指定したhtml_nameに紐付く、html_valueを**String型**で返す。

ただし、紐付くhtml_nameが複数ある場合、
form[name]がlist型で返ってくる為、**AttributeErrorが発生**する。

```python
# 例1)
# 変数名:格納されるデータ:型
# ret:'text_value':<class str>
ret = form['text_name'].value
```

```python
# 例2)
# raise AttributeError
ret = form['hdn_name'].value
```

# まとめ
以上のようにcgi.FieldStorageを使ってフォームの情報を取り出す事で
Webページ間のデータの受け渡しや動的なhtml処理などを簡単に行えます。
とても便利。