リクエストオブジェクトとレスポンスオブジェクト
| revision-up-to: | 7127 (0.97pre SVN) |
|---|
簡単な概要
Django は、システム全体にわたって、リクエストとレスポンスオブジェクトを使っ て処理状態を受け渡します。
あるページへのリクエストを受け取ると、Django は HttpRequest オブジェク トを生成します。このオブジェクトにはリクエストのメタデータが入っています。 次に Django は適切なビューをロードして、 HttpRequest をビュー関数の最初 の引数に渡します。各ビューは HttpResponse オブジェクトを返さねばなりま せん。
このドキュメントでは HttpRequest および HttpResponse オブジェクト の API について説明します。
HttpRequest オブジェクト
属性
session 以外の属性は全て読み出し専用です。
- path
リクエストしているページのフルパスを表す、ドメインを含まない文字列です。
例: "/music/bands/the_beatles/"
- method
リクエストに使われた HTTP メソッドを表す文字列です。必ず大文字になります。 例:
if request.method == 'GET': do_something() elif request.method == 'POST': do_something_else()- encoding
開発版の Django で新たに登場した機能です。
提出されたフォームデータのデコードに使われる、現在のエンコーディングを 表す文字列です (None の場合もありますが、この場合は DEFAULT_CHARSET を使います)。この属性を変更すれば、フォームデータに アクセスする際に使われるエンコーディングを指定できます。一度エンコーディ ングを変更すると、変更後に (GET や POST の) 属性へのアクセスは すべて新しい encoding の値に従って行われます。フォームデータが DEFAULT_CHARSET 以外の特定のエンコーディングと分かっている場合に便 利です。
- GET
- 全ての HTTP GET パラメタが入った辞書ライクなオブジェクトです。後述の QueryDict も参照してください。
- POST
全ての HTTP POST パラメタが入った辞書ライクなオブジェクトです。後述の QueryDict も参照してください。
フォームを POST HTTP メソッドで要求し、その際に何らフォームデータを伴わ ないような場合には、リクエストが POST で送られていながらも POST 辞 書が空になることがあります。従って、リクエストが POST メソッドであるか どうかを調べるために if request.POST を使うべきではありません。代わ りに if request.method == "POST" を使ってください (上参照)。
POST にはファイルアップロードに関する情報は 入っていない ので注意 してください。 FILES を参照してください。
- REQUEST
便宜的な辞書オブジェクトで、 POST パラメタをまず検索してから、次に GET パラメタを検索します。 PHP の $_REQUEST にインスパイアされ た機能です。
例えば、 GET = {"name": "john"} で POST = {"age": '34'} の場合、 REQUEST["name"] は "john" になり、 REQUEST["age"] は "34" になります。
通常は GET および POST を使うように強く勧めます。その方が明示的 だからです。
- COOKIES
- 全てのクッキーが入った標準の Python 辞書オブジェクトです。キーと値は文 字列です。
- FILES
アップロードされたファイル全てが入っている辞書ライクオブジェクトです。 FILES の各キーは <input type="file" name="" /> の name です。 FILES の各値は標準の Python 辞書オブジェクトで、以下の 3 つ のキーを持っています:
- filename -- アップロードされたファイルの名前を Python 文字列 で表したものです。
- content-type -- アップロードされたファイルのコンテンツ形式で す。
- content -- アップロードされたファイルの内容そのものです。
FILES にデータが入るのは、リクエストが POST であり、かつリクエ ストをポストした <form> に enctype="multipart/form-data がある 場合だけです。それ以外の場合、 FILES は空の辞書ライクオブジェクトに なります。
- META
標準の Python 辞書オブジェクトで、利用できる全ての HTTP ヘッダが入って います。利用可能なヘッダはクライアントとサーバごとに違いますが、例えば 以下のようなヘッダを利用できます:
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT_ENCODING
- HTTP_ACCEPT_LANGUAGE
- HTTP_HOST -- クライアントから送信された HTTP Host ヘッダです。
- HTTP_REFERER -- リクエスト対象のページを参照しているページが ある場合、そのページの URL です。
- HTTP_USER_AGENT -- クライアントのユーザエージェントを表す文字 列です。
- QUERY_STRING -- パース前の単一のクエリ文字列です。
- REMOTE_ADDR -- クライアントの IP アドレスです。
- REMOTE_HOST -- クライアントのホスト名です。
- REQUEST_METHOD -- "GET" や "POST" のような文字列です。
- SERVER_NAME -- サーバのホスト名です。
- SERVER_PORT -- サーバのポート番号です。
- user
現在ログインしているユーザを表す django.models.auth.models.User オブ ジェクトです。ユーザが現在ログインしていない場合には、 user は django.contrib.auth.models.AnonymousUser のインスタンスになります。 is_authenticated() を使うと、これら二種類のユーザを区別できます:
if request.user.is_authenticated(): # Do something for logged-in users. else: # Do something for anonymous users.user を利用できるのは、 インストールした Django で AuthenticationMiddleware を有効にした場合だけです。詳しくは Web リクエストの認証 を参照してください。
- session
読み書き可能な辞書ライクオブジェクトで、現在のセッションを表現しています。 この辞書はインストールされている Django でセッションが有効な場合にのみ 利用できます。詳しくは セッションのドキュメント を参照してください。
- raw_post_data
- HTTP POST データそのものです。高度な処理を行いたいときに便利です。普段 は POST を使ってください。
メソッド
- __getitem__(key)
キーに対する GET/POST 値を返します。 POST をまず調べ、次に GET を調べま す。キーが存在しなければ KeyError を送出します。
このメソッドによって、 HttpRequest インスタンスを辞書のように扱えま す。例えば、 request.POST または request.GET に "foo" とい うキーがあれば、 request["foo"] は True を返します。
- has_key()
- request.GET または request.POST に指定の値が入っているかどうか によって True または False を返します。
- get_host()
開発版の Django で新たに登場した機能です。
リクエストの送信元を HTTP_X_FORWARDED_HOST または HTTP_HOST ヘッ ダを (順に) 調べて返します。クライアントがこれらの値を提供していない場合、 PEP 333 に従って、 SERVER_NAME と SERVER_PORT の組み合わせを 返します。
Example: "127.0.0.1:8000"
- get_full_path()
path と、そのあとに続くクエリ文字列があれば返します。
例: "/music/bands/the_beatles/?print=true"
- build_absolute_uri(location)
開発版の Django で新たに登場した機能です。
location の絶対 URI を計算して返します。引数 location を省略する と、 location の値として request.get_full_path() を使います。
location の値がすでに絶対 URI であれば、値を変更しません。そうでない 場合、リクエスト中のサーバに関する変数を使って URI を構築します。
例: "http://example.com/music/bands/the_beatles/?print=true"
- is_secure()
- リクエストがセキュアである、すなわち HTTPS を介したリクエストのときに True を返します。
QueryDict オブジェクト
HttpRequest オブジェクト内では、 GET と POST 属性は django.http.QueryDict のインスタンスです。 QueryDict は辞書ライクな クラスで、同じキーに対して複数の値を取り得るようにカスタマイズされています。 これは、 HTML のフォーム要素には、例えば <select multiple="multiple"> のように、同じキーに対して複数の値を渡すものがあるからです。
QueryDict インスタンスは、 copy() を作らないかぎり変更できません。 これは、 request.POST や request.GET の属性を直接変更できないと いうことです。
QueryDict は辞書型のサブクラスなので、全ての標準的な辞書型のメソッドを 実装しています。ただし、以下の点が異なります:
__getitem__(key) -- 指定のキーに対する値を返します。一つのキーに 複数の値が存在する場合、 __getitem__() はリストの末尾の値を返しま す。キーに対応する値がなければ、 django.utils.datastructure.MultiValueDictKeyError を送出します。 (この例外は KeyError のサブクラスなので、 KeyError を見張って いれば捕捉できます。)
__setitem__(key, value) -- 指定のキーに対する値を [value] (value という値が一つだけ入ったリスト) にします。副作用をともなう 他の関数と同じく、このメソッドを呼び出せるのは (copy() を使って生 成したオブジェクトのような) 変更可能な QueryDict だけです。
__contains__(key) -- 指定のキーが設定されている場合に True を 返します。これにより、 if "foo" in request.GET のように書けます。
get(key, default) -- 上の __getitem__() と同じロジックですが、 キーに対応する値がないときにデフォルト値を返すフックがあります。
has_key(key)
setdefault(key, default) -- 標準の辞書型の setdefault() と同 じですが、内部的に __setitem__ を使います。
update(other_dict) -- QueryDict または標準の辞書型を引数にと ります。標準の辞書型の update() メソッドと同じですが、現在の値を 置き換えるのではなく、現在の値のリストに 追加 します。例えば:
>>> q = QueryDict('a=1') >>> q = q.copy() # to make it mutable >>> q.update({'a': '2'}) >>> q.getlist('a') ['1', '2'] >>> q['a'] # returns the last ['2']items() -- 標準の辞書型の items() メソッドと同じですが、 __getitem()__ と同じ、最後の値を返すロジックを使います。例えば:
>>> q = QueryDict('a=1&a=2&a=3') >>> q.items() [('a', '3')]values() -- 標準の辞書型の values() メソッドと同じですが、 __getitem()__ と同じ、最後の値を返すロジックを使います。例えば:
>>> q = QueryDict('a=1&a=2&a=3') >>> q.values() ['3']
加えて、 QueryDict には以下のメソッドがあります:
copy() -- Python 標準ライブラリの copy.deepcopy() を使って オブジェクトのコピーを生成して返します。コピーは変更可能になり、 値を変更できます。
getlist(key) -- 要求されたキーに対して、 Python のリスト型を返し ます。キーに対応する値がなければ空のリストを返します。このメソッドは 確実に何らかのリストを返します。
setlist(key, list_) -- キーに対して list_ を対応づけます (__setitem__() と違うところです)。
appendlist(key, item) -- キーに関連づけられている内部的なリストに 要素を追加します。
setlistdefault(key, default_list) -- setdefault に似ています が、単一の値ではなく値のリストを引数にとります。
lists() -- items() に似ていますが、全ての値をリストで返しま す。例えば:
>>> q = QueryDict('a=1&a=2&a=3') >>> q.lists() [('a', ['1', '2', '3'])]urlencode() -- データをクエリ文字列形式にフォーマットした文字列を 返します。例えば: "a=2&b=3&b=5" のようになります。
使用例
HTML フォームの例と、それに対して Django がどのように入力を扱うかを例で説明 しましょう:
<form action="/foo/bar/" method="post">
<input type="text" name="your_name" />
<select multiple="multiple" name="bands">
<option value="beatles">The Beatles</option>
<option value="who">The Who</option>
<option value="zombies">The Zombies</option>
</select>
<input type="submit" />
</form>
ユーザが your name フィールドに "John Smith" を指定し、複数選択ボッ クスで "The Beatles" と "The Zombies" にチェックを入れたとします。 Django のリクエストオブジェクトは以下のようになります:
>>> request.GET
{}
>>> request.POST
{'your_name': ['John Smith'], 'bands': ['beatles', 'zombies']}
>>> request.POST['your_name']
'John Smith'
>>> request.POST['bands']
'zombies'
>>> request.POST.getlist('bands')
['beatles', 'zombies']
>>> request.POST.get('your_name', 'Adrian')
'John Smith'
>>> request.POST.get('nonexistent_field', 'Nowhere Man')
'Nowhere Man'
実装上に関する注意
GET, POST, COOKIES, FILES, META, REQUEST, raw_post_data および user といった属性はすべて遅延読み込み (lazily load) されます。すなわち、 Django はコード中で要求されるまで、これらの値を 計算するためにリソースを消費しません。
HttpResponse オブジェクト
Django によって自動生成される HttpRequest オブジェクトとは対象的に、 HttpResponse オブジェクトは自分で生成せねばなりません。ビューを書くとき にはいつでも、 HttpResponse インスタンスを生成して、値を設定し、戻り値 として返さねばなりません。
HttpResponse クラスは django.http で定義されています。
使いかた
文字列を渡す
HttpResponse の典型的な使い方は、ページの内容を文字列としてコンストラク タに渡すというものです:
>>> response = HttpResponse("Here's the text of the Web page.")
>>> response = HttpResponse("Text only, please.", mimetype="text/plain")
コンテンツを累積的に追加していきたい場合には、 response をファイルライ クオブジェクトのようにも使えます:
>>> response = HttpResponse()
>>> response.write("<p>Here's the text of the Web page.</p>")
>>> response.write("<p>Here's another paragraph.</p>")
ヘッダの追加や削除は辞書とおなじ書法で書けます:
>>> response = HttpResponse() >>> response['X-DJANGO'] = "It's the best." >>> del response['X-PHP'] >>> response['X-DJANGO'] "It's the best."
該当するヘッダがなくても、 del は KeyError を送出しないので気をつけ てください。
イテレータを渡す
最後に、ハードコードされた文字列ではなくイテレータも HttpResponse に渡 せます。このテクニックを使う場合は以下のガイドラインに従って下さい:
- イテレータは文字列を返さねばなりません。
- イテレータをコンテンツに指定して HttpResponse を初期化した場合、 HttpResponse インスタンスはファイルライクオブジェクトとして扱えず、 ファイルライクオブジェクトとして操作すると Exception を送出します。
メソッド
- __init__(content='', mimetype=None, status=200, content_type=DEFAULT_CONTENT_TYPE)
指定のページコンテンツ (文字列) と MIME タイプで HttpResponse オブ ジェクトをインスタンス化します。 DEFAULT_CONTENT_TYPE は 'text/html' です。
content はイテレータまたは文字列にできます。イテレータにする場合、 イテレータは文字列を返さねばなりません。イテレータを指定した場合、レス ポンスの内容はイテレータの返す文字列を結合して生成されます。
status はレスポンスの HTTP 状態コード です。
(開発版の Django で新たに登場した機能) content_type は mimetype の別名にすぎません。以前、このパラメタには mimetype と いう名前しかありませんでしたが、実際のところ、このパラメタに指定する値 は HTTP の Content-Type ヘッダに入る内容であり、MIME タイプ仕様には ない文字セットエンコーディングの指定を含んでいました。そこで、 mimetype が指定されている (None でない) 場合にはその値を使い、 それ以外の場合には content_type を使うように変更しました。どちらの パラメタも省略すると、 DEFAULT_CONTENT_TYPE 設定を使います。
- __setitem__(header, value)
- ヘッダ名と値を設定します。 header と value は文字列にせねばなり ません。
- __delitem__(header)
- 指定の名前のヘッダを削除します。ヘッダが存在しなければ、暗黙のうちに失 敗します。大小文字を区別します。
- __getitem__(header)
- 指定のヘッダ名に対応する値を返します。大小文字を区別します。
- has_header(header)
- 大小文字を区別せずに指定の名前のヘッダがあるか調べ、 True または False を返します。
- set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None)
クッキーを設定します。パラメタは Python 標準ライブラリの Morsel オブジェクト と同じ形式です。
- max_age には秒数または None (デフォルト値) を指定します。 デフォルト値では、クッキーはクライアントブラウザとのセッションの 間だけ持続します。
- expires は "Wdy, DD-Mon-YY HH:MM:SS GMT" の形式の文字列で す。
- 別のドメインのクッキー (cross-domain cookie) を設定したい場合には、 domain を使います。例えば、 domain=".lawrence.com" にする と、 www.lawrence.com, blogs.lawrence.com, calendars.lawrence.com といったサイトでだけ読めるようになります。それ以外の場合、クッキー はクッキーを設定したドメインでしか読めません。
- delete_cookie(key, path='/', domain=None)
指定のキーに対するクッキーを削除します。キーが存在しなければ、暗黙のう ちに失敗します。
cookie の動作原理上、 path と domain を set_cookie() に指定 した値と同じにしないと、クッキーを削除できなくなります。
- content
- Python 文字列の内容を返します。必要ならば Unicode オブジェクトにエンコー ドします。メソッドではなくプロパティなので、 r.content() ではなく r.content になることに注意して下さい。
- write(content), flush(), tell()
- HttpResponse インスタンスをファイルライクオブジェクトのように扱うた めのメソッドです。
HttpResponse のサブクラス
Django には、様々なタイプの HTTP レスポンスを扱うための HttpResponse の サブクラスがあります。これらのサブクラスは HttpResponse と同じく django.http モジュールにあります。
- HttpResponseRedirect
- コンストラクタはリダイレクト先のパスを示す引数を一つだけ取ります。リダ イレクト先は完全指定の URL (例えば "http://www.yahoo.com/search/") でも、ドメイン名のない絶対 URL ( "/search/") でもかまいません。この レスポンスオブジェクトは HTTP 状態コード 302 を返します。
- HttpResponsePermanentRedirect
- HttpResponseRedirect と同じですが、"found" リダイレクト (HTTP 状態 コード 302) ではなく永続リダイレクト (状態コード 301) を使います。
- HttpResponseNotModified
- コンストラクタは引数をとりません。ユーザが最後にリクエストしたときから ページが変更されていないこと (状態コード 304) を知らせるために使います。
- HttpResponseBadRequest
- 開発版の Django で新たに登場した機能です。 HttpResponse と同じように振舞いますが、状態コード 400 を使います。
- HttpResponseNotFound
- HttpResponse と同じですが、状態コード 404 を使います。
- HttpResponseForbidden
- HttpResponse と同じですが、状態コード 403 を使います。
- HttpResponseNotAllowed
- HttpResponse と同じですが、状態コード 405 を使います。許可されてい る HTTP メソッドのリスト (例えば ['GET', 'POST']) を必須の引数とし てとります。
- HttpResponseGone
- HttpResponse と同じですが、状態コード 410 を使います。
- HttpResponseServerError
- HttpResponse と同じですが、状態コード 500 を使います。
エラーを返す
Django では、簡単に HTTP エラーコードを返せます。エラー応答は、すでに述べた HttpResponseNotFound, HttpResponseForbidden, HttpResponseServerError といったサブクラスのインスタンスを作成して、以 下の例のように通常の HttpResponse の代わりに返すだけです:
def my_view(request):
# ...
if foo:
return HttpResponseNotFound('<h1>Page not found</h1>')
else:
return HttpResponse('<h1>Page was found</h1>')
ただし、 404 エラーは他の HTTP エラーよりはるかに良く使われるエラーなので、 もっと簡単に扱う方法を提供しています。
Http404 例外
HttpResponseNotFound のようなエラーを返す場合、以下のように、エラーペー ジの中身になる HTML を指定せねばなりません:
return HttpResponseNotFound('<h1>Page not found</h1>')
これはちょっと不便ですね。それに、サイト全体で一貫した 404 エラーページを用 意しておく方が賢明です。そこで、 Django には Http404 例外があります。 ビュー関数のどこかで Http404 例外を送出すると、 Django はこのエラーを捕 捉して、サイト標準のエラーページを HTTP エラーコード 404 で返します。
例を示しましょう:
from django.http import Http404
def detail(request, poll_id):
try:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404
return render_to_response('polls/detail.html', {'poll': p})
Http404 例外を使うには、 404 エラーの送出時に表示されるテンプレートを作 成しておかねばなりません。このテンプレートの名前は 404.html で、テンプ レートツリーの一番上に配置せねばなりません。
エラービューのカスタマイズ
404 (ページが見つかりません) ビュー
Http404 例外を送出すると、 Django は 404 エラー処理用の特殊なビューをロー ドします。デフォルトでは、このビューは django.views.defaults.page_not_found に設定されています。 django.views.defaults.page_not_found は 404.html という名前のテンプ レートをロードしてレンダします。
このため、テンプレートディレクトリの再上階層に 404.html という名前のテ ンプレートを作成しておかねばなりません。このテンプレートは全ての 404 エラー に対して用いられます。
- page_not_found ビューは 99% の Web アプリケーションの要求を満たすはずで
すが、 404 ビューを自作したい場合には、URLconf で以下のようにして handler404 を指定します:
handler404 = 'mysite.views.my_custom_404_view'
舞台裏では、 Django は handler404 を介して 404 ビューを捜し出します。デ フォルトでは、 URLconf の以下の行:
from django.conf.urls.defaults import *
によって、 handler404 が現在のモジュールに取り込まれます。 django/conf/urls/defaults.py を見れば分かりますが、 handler404 のデ フォルト値は 'django.views.defaults.page_not_found' に設定されています。
404 ビューについて、知っておかねばならないことが 3 つあります:
- 404 ビューは、リクエストされた URL に対して、 Django が URLconf の全 ての正規表現を調べた結果、一致するものをみつけられなかった場合にも呼 び出されます。
- 404 ビューを自作せず、ただデフォルトのビューを使う場合でも、一つだけ やらねばならないこととして、 404.html という名前のテンプレートを 作成せねばなりません。このテンプレートはテンプレートディレクトリの最 上階層に配置します。デフォルトの 404 ビューは全ての 404 エラーに対 して同じテンプレートを使います。デフォルトの 404 ビューは、 404 エラー を引き起こした URL を、``request_path`` という変数としてテンプレート に渡します。
- 404 ビューに渡されるコンテキストは RequestContext なので、 テンプレートには TEMPLATE_CONTEXT_PROCESSORS で追加した変数も 渡ります。
- (settings モジュールで) DEBUG を True にすると、 404 ビューは 呼び出されず、代わりにトレースバックが表示されます。
500 (サーバエラー) ビュー
404 エラーと同様に、 Django はビューのコード上で実行時エラーに遭遇した場合 の挙動も特別扱いしています。ビューを実行した結果、例外が送出されると、 Django はデフォルトで django.views.defaults.server_error というビューを 呼び出します。このビューは 500.html というテンプレートをロードしてレン ダします。
このため、テンプレートディレクトリの再上階層に 500.html という名前のテ ンプレートを作成しておかねばなりません。このテンプレートは全ての 500 エラー に対して用いられます。デフォルトの 500 ビューはテンプレートに一切変数を渡さ ず、空の Context インスタンスを渡してレンダリングを実行しますが、これは さらなるエラーが発生するのを防ぐためです。
server_error ビューは 99% の Web アプリケーションの要求を満たすはずです が、 500 ビューを自作したい場合には、URLconf で以下のようにして handler500 を指定します:
handler500 = 'mysite.views.my_custom_error_view'
舞台裏では、 Django は handler500 を介して 500 ビューを捜し出します。デ フォルトでは、 URLconf の以下の行:
from django.conf.urls.defaults import *
によって、 handler500 が現在のモジュールに取り込まれます。 django/conf/urls/defaults.py を見れば分かりますが、 handler500 のデ フォルト値は 'django.views.defaults.server_error' に設定されています。