クイックスタート—Werkzeugのドキュメント

提供:Dev Guides
Werkzeug/docs/1.0.x/quickstart
移動先:案内検索

クイックスタート

ドキュメントのこの部分は、Werkzeugの最も重要な部分の使用方法を示しています。 これは、 PEP 333 (WSGI)および RFC 2616 (HTTP)の基本を理解している開発者向けの出発点として意図されています。

警告

ドキュメントが示唆する場所からすべてのオブジェクトをインポートするようにしてください。 理論的には、状況によっては異なる場所からオブジェクトをインポートすることが可能ですが、これはサポートされていません。

たとえば、MultiDictは werkzeug モジュールのメンバーですが、内部的に別のモジュールに実装されています。


WSGI環境

WSGI環境には、ユーザーリクエストがアプリケーションに送信するすべての情報が含まれています。 これはWSGIアプリケーションに渡されますが、create_environ()ヘルパーを使用してWSGI環境辞書を作成することもできます。

>>> from werkzeug.test import create_environ
>>> environ = create_environ('/foo', 'http://localhost:8080/')

これで、遊ぶ環境ができました。

>>> environ['PATH_INFO']
'/foo'
>>> environ['SCRIPT_NAME']
''
>>> environ['SERVER_NAME']
'localhost'

通常、環境はバイト文字列に制限されており、フォームデータに手動で解析する以外にアクセスする方法がないため、環境を直接操作することは誰も望んでいません。


リクエストを入力してください

リクエストデータにアクセスするには、Requestオブジェクトの方がはるかに楽しいです。 環境をラップし、そこからのデータへの読み取り専用アクセスを提供します。

>>> from werkzeug.wrappers import Request
>>> request = Request(environ)

これで、重要な変数にアクセスできるようになり、Werkzeugがそれらを解析して、意味のある場所でデコードします。 リクエストのデフォルトの文字セットは utf-8 に設定されていますが、Requestをサブクラス化することで変更できます。

>>> request.path
u'/foo'
>>> request.script_root
u''
>>> request.host
'localhost:8080'
>>> request.url
'http://localhost:8080/foo'

また、リクエストに使用されたHTTPメソッドを確認することもできます。

>>> request.method
'GET'

このようにして、POST / PUTリクエストで送信されたURL引数(クエリ文字列)とデータにアクセスすることもできます。

テストの目的で、from_values()メソッドを使用して、提供されたデータからリクエストオブジェクトを作成できます。

>>> from cStringIO import StringIO
>>> data = "name=this+is+encoded+form+data&another_key=another+one"
>>> request = Request.from_values(query_string='foo=bar&blah=blafasel',
...    content_length=len(data), input_stream=StringIO(data),
...    content_type='application/x-www-form-urlencoded',
...    method='POST')
...
>>> request.method
'POST'

これで、URLパラメータに簡単にアクセスできます。

>>> request.args.keys()
['blah', 'foo']
>>> request.args['blah']
u'blafasel'

提供されたフォームデータについても同じです。

>>> request.form['name']
u'this is encoded form data'

この例からわかるように、アップロードされたファイルの処理はそれほど難しくありません。

def store_file(request):
    file = request.files.get('my_file')
    if file:
        file.save('/where/to/store/the/file.txt')
    else:
        handle_the_error()

ファイルはFileStorageオブジェクトとして表され、それらを操作するためのいくつかの一般的な操作を提供します。

headers属性を使用して、リクエストヘッダーにアクセスできます。

>>> request.headers['Content-Length']
'54'
>>> request.headers['Content-Type']
'application/x-www-form-urlencoded'

もちろん、ヘッダーのキーでは大文字と小文字は区別されません。


ヘッダーの解析

もっとある。 Werkzeugは、頻繁に使用されるHTTPヘッダーやその他のリクエストデータへの便利なアクセスを提供します。

一般的なWebブラウザーが送信するすべてのデータを使用して要求オブジェクトを作成し、それを試してみましょう。

>>> environ = create_environ()
>>> environ.update(
...     HTTP_USER_AGENT='Mozilla/5.0 (Macintosh; U; Mac OS X 10.5; en-US; ) Firefox/3.1',
...     HTTP_ACCEPT='text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
...     HTTP_ACCEPT_LANGUAGE='de-at,en-us;q=0.8,en;q=0.5',
...     HTTP_ACCEPT_ENCODING='gzip,deflate',
...     HTTP_ACCEPT_CHARSET='ISO-8859-1,utf-8;q=0.7,*;q=0.7',
...     HTTP_IF_MODIFIED_SINCE='Fri, 20 Feb 2009 10:10:25 GMT',
...     HTTP_IF_NONE_MATCH='"e51c9-1e5d-46356dc86c640"',
...     HTTP_CACHE_CONTROL='max-age=0'
... )
...
>>> request = Request(environ)

最も役に立たないヘッダーから始めましょう:ユーザーエージェント:

>>> request.user_agent.browser
'firefox'
>>> request.user_agent.platform
'macos'
>>> request.user_agent.version
'3.1'
>>> request.user_agent.language
'en-US'

より便利なヘッダーはacceptヘッダーです。 このヘッダーを使用して、ブラウザーはWebアプリケーションに、処理できるmimetypeとその処理方法を通知します。 すべてのacceptヘッダーは品質でソートされ、最良のアイテムが最初になります。

>>> request.accept_mimetypes.best
'text/html'
>>> 'application/xhtml+xml' in request.accept_mimetypes
True
>>> print request.accept_mimetypes["application/json"]
0.8

同じことが言語でも機能します。

>>> request.accept_languages.best
'de-at'
>>> request.accept_languages.values()
['de-at', 'en-us', 'en']

そしてもちろん、エンコーディングと文字セット:

>>> 'gzip' in request.accept_encodings
True
>>> request.accept_charsets.best
'ISO-8859-1'
>>> 'utf-8' in request.accept_charsets
True

正規化が利用できるため、代替フォームを安全に使用して包含チェックを実行できます。

>>> 'UTF8' in request.accept_charsets
True
>>> 'de_AT' in request.accept_languages
True

Eタグおよびその他の条件付きヘッダーも解析された形式で利用できます。

>>> request.if_modified_since
datetime.datetime(2009, 2, 20, 10, 10, 25)
>>> request.if_none_match
<ETags '"e51c9-1e5d-46356dc86c640"'>
>>> request.cache_control
<RequestCacheControl 'max-age=0'>
>>> request.cache_control.max_age
0
>>> 'e51c9-1e5d-46356dc86c640' in request.if_none_match
True

反応

応答オブジェクトは、要求オブジェクトの反対です。 これらは、クライアントにデータを送り返すために使用されます。 実際には、応答オブジェクトは、栄光に満ちたWSGIアプリケーションにすぎません。

つまり、WSGIアプリケーションから応答オブジェクトを返すのではなく、WSGIアプリケーション内でWSGIアプリケーションとして呼び出しし、その呼び出しの戻り値を返すことです。

したがって、標準のWSGI「HelloWorld」アプリケーションを想像してみてください。

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return ['Hello World!']

応答オブジェクトを使用すると、次のようになります。

from werkzeug.wrappers import Response

def application(environ, start_response):
    response = Response('Hello World!')
    return response(environ, start_response)

また、リクエストオブジェクトとは異なり、レスポンスオブジェクトは変更されるように設計されています。 だからここにあなたがそれらでできることはあります:

>>> from werkzeug.wrappers import Response
>>> response = Response("Hello World!")
>>> response.headers['content-type']
'text/plain; charset=utf-8'
>>> response.data
'Hello World!'
>>> response.headers['content-length'] = len(response.data)

同じ方法で応答のステータスを変更できます。 コードだけを使用するか、メッセージも提供します。

>>> response.status
'200 OK'
>>> response.status = '404 Not Found'
>>> response.status_code
404
>>> response.status_code = 400
>>> response.status
'400 BAD REQUEST'

ご覧のとおり、属性は両方向で機能します。 したがって、statusstatus_codeの両方を設定すると、変更が他方に反映されます。

また、一般的なヘッダーは、属性として、またはそれらを設定/取得するためのメソッドとともに公開されます。

>>> response.content_length
12
>>> from datetime import datetime
>>> response.date = datetime(2009, 2, 20, 17, 42, 51)
>>> response.headers['Date']
'Fri, 20 Feb 2009 17:42:51 GMT'

etagは弱い場合も強い場合もあるため、次のように設定する方法があります。

>>> response.set_etag("12345-abcd")
>>> response.headers['etag']
'"12345-abcd"'
>>> response.get_etag()
('12345-abcd', False)
>>> response.set_etag("12345-abcd", weak=True)
>>> response.get_etag()
('12345-abcd', True)

一部のヘッダーは、可変構造として使用できます。 たとえば、ほとんどの Content- ヘッダーは値のセットです。

>>> response.content_language.add('en-us')
>>> response.content_language.add('en')
>>> response.headers['Content-Language']
'en-us, en'

また、ここではこれは両方向で機能します。

>>> response.headers['Content-Language'] = 'de-AT, de'
>>> response.content_language
HeaderSet(['de-AT', 'de'])

認証ヘッダーもそのように設定できます。

>>> response.www_authenticate.set_basic("My protected resource")
>>> response.headers['www-authenticate']
'Basic realm="My protected resource"'

クッキーも設定できます:

>>> response.set_cookie('name', 'value')
>>> response.headers['Set-Cookie']
'name=value; Path=/'
>>> response.set_cookie('name2', 'value2')

ヘッダーが複数回表示される場合は、getlist()メソッドを使用してヘッダーのすべての値を取得できます。

>>> response.headers.getlist('Set-Cookie')
['name=value; Path=/', 'name2=value2; Path=/']

最後に、すべての条件値を設定した場合は、要求に対して応答を条件付きにすることができます。 つまり、リクエストにすでに情報が含まれていることを確認できる場合、トラフィックを節約するために、ヘッダー以外のデータはネットワーク経由で送信されません。 そのためには、少なくともetag(比較に使用される)と日付ヘッダーを設定してから、リクエストオブジェクトを使用してmake_conditionalを呼び出す必要があります。

それに応じて応答が変更されます(ステータスコードが変更され、応答本文が削除され、エンティティヘッダーが削除されますなど)。