たけし備忘録

自分の好奇心の赴くままに勉強メモ LL系が大好き Python bash Julia C

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


次の記事へ進む → 6.テンプレート


関連リンク