5.データリクエスト
データリクエスト
ボトルには、Cookie、ヘッダーとグローバル·リクエスト·オブジェクトを介してPOSTフォームデータなどのHTTP関連のメタデータへのアクセスを提供します。このオブジェクトは、いつものように長く、それがコールバック関数内からアクセスされると、現在の要求に関する情報が含まれています。これは、複数の要求が同時に処理され、マルチスレッド環境でも動作します。グローバルオブジェクトはスレッドセーフであることができる方法の詳細については、contextlocal参照してください。
注意
ボトルはFormsDictインスタンスで解析されたHTTPのメタデータのほとんどが格納されます。これらは通常の辞書と同じように動作しますが、いくつかの追加機能があります。辞書内のすべての値が属性として用意されています。これらの仮想属性は、常に値が欠落している場合でも、Unicode文字列を返します。その場合には、文字列は空です。
FormsDictはMultiDictのサブクラスであり、キーごとに複数の値を格納することができます。標準の辞書のアクセス方法は単一の値のみを返しますが、MultiDict.getall()メソッドは、特定のキーのすべての値のリスト(空かもしれません)を返します。
完全なAPIと機能のリストは、APIセクション(要求を参照)で説明されていますが、最も一般的なユースケースと機能はあまりにも、ここでカバーされています。
クッキー
クッキーはFormsDictとしてBaseRequest.cookiesに格納されています。 BaseRequest?.get_cookie()メソッドは、別のセクションで説明したように署名されたクッキーにアクセスすることができます。この例では、単純なクッキー·ベースのビュー·カウンタを示しています。
from bottle import route, request, response @route('/counter') def counter(): count = int( request.cookies.get('counter', '0') ) count += 1 response.set_cookie('counter', str(count)) return 'You visited this page %d times' % count
HTTPヘッダー
クライアントから送信されたすべてのHTTPヘッダー(例えばリファラ、エージェントまたはAccept-Language)をWSGIHeaderDictとBaseRequest.headersを介してアクセス可能に格納されています。 WSGIHeaderDictは、基本的に大文字と小文字を区別しないキーを持つ辞書です。
from bottle import route, request @route('/is_ajax') def is_ajax(): if request.headers.get('X-Requested-With') == 'XMLHttpRequest': return 'This is an AJAX request' else: return 'This is a normal request'
クエリ変数
クエリ文字列(/フォーラムのように?ID = 1&ページ= 5)は一般に、サーバーにキー/値ペアの数が少ないを送信するために使用されています。あなたは、文字列全体を取得するためにこれらの値とBaseRequest.query_string属性にアクセスするBaseRequest.query(FormsDict?)を使用することができます。
from bottle import route, request, response @route('/forum') def display_forum(): forum_id = request.query.id page = request.query.page or '1' return 'Forum ID: %s (page %s)' % (forum_id, page)
フォームデータとファイルのアップロードのPOST
POSTとPUTリクエストのリクエストボディは、さまざまな形式でエンコードされたフォームデータを含めることができます。 BaseRequest?.forms辞書はBaseRequest.filesに格納ファイルのアップロードとBaseRequest.POST一つに両方の辞書を組み合わせて、解析されたテキスト形式のフィールドが含まれています。 3すべてのFormsDictインスタンスで、オンデマンドで作成されます。ファイルのアップロードは、いくつかのメタデータと一緒に特別なcgi.FieldStorageオブジェクトとして保存されます。最後に、BaseRequest?.body経由でファイルライクオブジェクトとして生の身体データにアクセスすることができます。
ここで単純なファイルアップロードフォームの例は、次のとおりです。
ファイルを選択
from bottle import route, request @route('/upload', method='POST') def do_upload(): name = request.forms.name data = request.files.data if name and data and data.file: raw = data.file.read() # This is dangerous for big files filename = data.filename return "Hello %s! You uploaded %s (%d bytes)." % (name, filename, len(raw)) return "You missed a field."
Unicodeに関する問題
Python 2ではすべてのキーと値は、バイト文字列です。あなたは、Unicodeが必要な場合は、FormsDict?.getunicode()を呼び出すか、属性アクセスを介して値をフェッチできます。と失敗した場合は空の文字列を返します。どちらの方法で文字列(UTF8デフォルト)をデコードしてみてください。いいえUnicodeErrorをキャッチする必要はありません。
'Göttingen' # An utf8 string provisionally decoded as ISO-8859-1 by the server >>> request.query.city 'Göttingen' # The same string correctly re-encoded as utf8 by bottle
Python 3ではすべての文字列はUnicodeであるが、HTTPはバイトベースのワイヤプロトコルです。サーバは、それらがアプリケーションに渡される前に何らかの形でバイト列をデコードする必要があります。安全側であるためには、WSGIはISO-8859-1(別名は、latin1)、後で別のエンコーディングを使用して再エンコードすることができます可逆シングルバイトコーデックを示唆している。ボトルは、そのFormsDict.getunicode()と属性アクセスのためではなく、その他のdict-アクセスメソッドに対して行います。これらは、あなたが望むものはおそらくありませんサーバの実装によって提供変わらない値を返します。
>>> request.query['city'] 'Göttingen' # An utf8 string provisionally decoded as ISO-8859-1 by the server >>> request.query.city 'Göttingen' # The same string correctly re-encoded as utf8 by bottle
あなたは正しくデコードされた値(例えばWTForms用)全体の辞書が必要であれば、再エンコードされたコピーを取得しFormsDict.decode()を呼び出すことができます。
WSGI環境
各BaseRequestインスタンスはWSGI環境ディクショナリをラップします。オリジナルはBaseRequest.environに格納されますが、リクエストオブジェクト自体も、辞書のように動作しています。興味深いデータのほとんどは、特別なメソッドや属性を介して公開されていますが、直接WSGI環境変数にアクセスする場合は、そのように行うことができます。
@route('/my_ip') def show_ip(): ip = request.environ.get('REMOTE_ADDR') # or ip = request.get('REMOTE_ADDR') # or ip = request['REMOTE_ADDR'] return "Your IP is: %s" % ip
関連リンク