今回はREQUEST DATAのあたりを見ていきます。HTMLで作成したフォームの内容をサーバ側でどのように受取っていくかです。
REQUEST DATA
前回まとめたCookieや、HTTPヘッダー等はrequest
というオブジェクトを通じて操作しました。以下の様なHTMLの<form>
についても同じようにrequest
を通じて扱うことができます。
<form> <input type='text' name='username' /> <input type='password' name='password' /> </form>
bootleでは<form>
経由のデータやCookieはFormsDict
というPythonのdict
ライクなオブジェクトを通じて操作できるようにしています。FormsDict
は以下の特徴があります。
- Dictのように
data['key']
やdata.get('key')
でのアクセスができる data.key
の用に属性へのアクセスようにデータへアクセスができる
つまり、以下はいずれもcookie_key
というCookieへのアクセスになります。
# case1 print(type(request.cookies['cookie_key']), request.cookies['cookie_key']) # case2 print(type(request.cookies.get('cookie_key')), request.cookies.get('cookie_key')) # case3 print(type(request.get_cookie('cookie_key')), request.get_cookie('cookie_key')) # case4 print(type(request.cookies.cookie_key), request.cookies.cookie_key)
いずれもstrを戻しますが、マルチバイトのデータを格納している場合は挙動が異なります。以下が実際の結果です。
<class 'str'> ããããã <class 'str'> ããããã <class 'str'> ããããã <class 'str'> あいうえお
case4のみそのまま表示されています。case1-3は以下と同じ結果です。
>>> print('あいうえお'.encode('utf-8').decode('latin1')) ããããã
HTTPはByteベースでやりとりがされていますが、Python3からはすべての文字列はunicodeになりました。
bottleではrequest.cookies.cookie_key
という形式のアクセスではutf-8でdecodeした結果を戻しますが、それ以外の方式ではlatin1でdecodeした結果が戻っています。
任意のエンコードで取得するにはgetunicode
を使用します。
request.cookies.getunicode('cookie_key', encoding='utf-8')
これは以下と同義です。
# str -> bytes -> str request.cookies.get_cookie('cookie_key').encode('latin1').decode('utf-8')
cookieの場合は特にsigned_cookieがありますのでget_cookie
を使用せざるを得ないケースもあるので、その場合は上述のように一旦デフォルトのlatin-1
でencode
してbytes
に戻したあと、utf-8等でdecode
することが必要になるかもしれません。
なお、このあたりのbottle内のコードは以下です。
# bottle.py 2209行目あたり def getunicode(self, name, default=None, encoding=None): """ Return the value as a unicode string, or the default. """ try: return self._fix(self[name], encoding) except (UnicodeError, KeyError): return default : # 2184行目あたり input_encoding = 'utf8' recode_unicode = True def _fix(self, s, encoding=None): if isinstance(s, unicode) and self.recode_unicode: # Python 3 WSGI # 未指定の場合はinput_encoding(utf-8)でdecodeして戻す return s.encode('latin1').decode(encoding or self.input_encoding) elif isinstance(s, bytes): # Python 2 WSGI return s.decode(encoding or self.input_encoding) else: return s
Fromからの取り出し
それでは簡単なHTMLからデータを受け取るサンプルを確認しておきます。ファイルは以下の構成にします。
├── form.py └── views └── form.html
まず以下のHTMLをviews/form.html
として作成します。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>form test</title> </head> <body> <h3>ログインフォーム</h3> <form method="POST" action="form_test"> <input type="text" name='login_name' placeholder="username" /><br/> <input type="password" name='login_pass' placeholder="password" /><br/> <input type="submit" value="ログイン" /> </form> </body> </html>
アプリケーション用のコードとしてform.py
として以下を作成します。
# coding:utf-8 from bottle import ( run, request, template, get, post ) # URLを直接指定したり、リンクで飛んだ場合はこちら @get('/form_test') def get_form_test(): return template('form.html') # form等でPOSTでアクセスした場合はこちら @post('/form_test') def post_form_test(): login_name = request.forms.getunicode('login_name') login_password = request.forms.getunicode('login_pass') return 'id:{} pass:{}'.format(login_name, login_password) if __name__ == "__main__": # テスト用のサーバをlocalhost:8080で起動する # reloader=Trueにより、ソースを書き換えると自動的に再起動される run(host='localhost', port=8080, reloader=True, debug=True)
get_form_test
もpost_form_test
もhttp://host:port/form_test
というURLに紐付いていますが、それぞれGETメソッド、POSTメソッドに対応しています。そのため、ブラウザでURLを直接指定した場合やリンクで移動した場合はまずget_form_test
が実行されます。
return template('form.html')
はviews/form.html
の内容をクライアントに戻す動きをします。そのため、最初に作成したform.html
がブラウザに戻され以下のような画面が表示されます。
それぞれの入力欄に値を指定してログイン
を実行すると<form method="POST" action="form_test">
に指定されているように、http://host:port/form_test
へPOST
アクセスが行われます。そのため、処理がpost_form_test
に移ります。
post_form_test
ではlogin_name = request.forms.getunicode('login_name')
といった形でフォームに入力したデータを取り出しています。指定しているlogin_name
というキーはHTMLのformタグ内の<input type="text" name='login_name' placeholder="username" />
のname
と一致しています。この様に入力用のinputタグに指定したnameで実際に入力された内容が取り出せます。
あとは受け取った内容を単にクライアントにreturn 'id:{} pass:{}'.format(login_name, login_password)
と指定して戻していますので、実際に入力した内容がブラウザに表示されます。
まとめ
最低限ではありますがformでの入力情報の取り出しと、bottleにおけるデータの取得についてまとめました。cookieと組み合わせればログイン機構の基本的なところはこれで実現できると思います。