ミドルウェア

revision-up-to:17812 (1.4)

ミドルウェア (Middleware) とは、 Django のリクエスト/レスポンス処理をフック するためのフレームワークです。ミドルウェアは軽量かつ低水準な「プラグイン」 システムで、Django の入出力を操作します。

各ミドルウェアコンポーネントはそれぞれ特定の機能を担っています。例えば、 Django には XViewMiddleware ミドルウェアコンポーネントがありますが、こ れは全ての HEAD リクエストに対して "X-View" HTTP ヘッダを追加します。

このドキュメントでは、 Django についてくる全てのミドルウェアコンポーネント の使用法と、自分で新たにミドルウェアを作る方法を説明します。 Django には、すぐに使える組み込みのミドルウェアが付属しています。 組み込みミドルウェアガイド を参照してください。

ミドルウェアの有効化

ミドルウェアコンポーネントを有効化するには、Django 設定ファイルの MIDDLEWARE_CLASSES リストにコンポーネントを追加します。コンポー ネント名は文字列で指定し、ミドルウェアのクラス名を完全な Python パスで表し ます。例えば、 django-admin.py startproject が生 成するデフォルトの設定ファイルにある MIDDLEWARE_CLASSES は以下の ようになっています:

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)

リクエストの処理フェーズでは、Django は MIDDLEWARE_CLASSES に指定された順番で (process_request() および process_view`()) ミドルウェアを適用していきます。レスポンスの処理フェーズでは、 (process_response() および process_exception() ) ミドルウェア が逆順に適用されます。この仕組みは、タマネギの構造になぞらえて、ミドルウェ アクラスを「層」だと考えるとよいでしょう:

Middleware application order.

Django はミドルウェアがなくても動作します – 望むなら MIDDLEWARE_CLASSES は空でもよいのです。とはいえ、少なくとも CommonMiddleware は使うように強く勧めます。

ミドルウェアを自作する

ミドルウェアの自作は簡単です。各ミドルウェアコンポーネントは、以下のメソッ ドを少なくとも一つ定義しているような単一の Python クラスです:

process_request

process_request(self, request)

requestHttpRequest オブジェクトです。このメソッ ドはリクエストごとに Django がどのビューを実行するか決定する前に呼び出されます。

process_request()None または HttpResponse オブジェクトのいずれかを返さねばなりません。 None を返した場合、 Django はリクエストの処理を継続し、他のミドルウェアや適切なビューを実行します。 HttpResponse オブジェクトを返した場合、 Django は他の リクエストミドルウェア、ビューミドルウェア、例外ミドルウェア、あるいは URLconf で設定されたビューを呼び出さず、 HttpResponse オブジェクトをそのまま返します。レスポンスミドルウェアは必ず呼び出されます。

process_view

process_view(self, request, view_func, view_args, view_kwargs)

requestHttpRequest オブジェクトです。 view_func は Django がビュー関数としてこれから呼び出そうとしている Python の関数です、 (実際の関数オブジェクトで、関数名を表す文字列ではありま せん)。 view_args にはビューに渡されることになる固定引数が、 view_kwargs にはビューに渡されることになるキーワード引数の辞書が入って います。 view_args と``view_kwargs`` のいずれにも、ビューの第一引数 (request) は入っていません。

process_view() は Django がビュー関数を呼び出す直前に呼び出されます。こ の関数は None または HttpResponse オブジェクトを 返さねばなりません。 None を返した場合、 Django は処理を継続し、他のミ ドルウェアの process_view() を試した後、適切なビュー関数を呼び出します。 HttpResponse オブジェクトを返した場合、 Django は他の リクエストミドルウェア、ビューミドルウェア、例外ミドルウェア、あるいは URLconf で設定されたビューを呼び出さず、 HttpResponse オブジェクトをそのまま返します。レスポンスミドルウェアは必ず呼び出されます。

Note

process_request や``process_view`` からミドルウェアの中の request.POSTrequest.REQUEST にアクセスするとそのミドルウェアの後で実行される任意のビューが リクエストのアップロードハンドラーを動的に変更する ことができなくなるので避けるべきです。

CsrfViewMiddleware クラスは例外と 考えることができます。 csrf_exempt() デコレータと csrf_protect() デコレータでは ビューはCSRF検証が行われる時点で明示的に制御することができるからです。

process_template_response

Django 1.3 で新たに登場しました: リリースノートを参照してください
process_template_response(self, request, response)

requestHttpRequest クラスのオブジェクトです。 responseSimpleTemplateResponse クラスのサブクラス (例えば TemplateResponse) 、あるいは render メソッドを実装する任意の response オブジェクトです。

process_template_response()render メソッドを実装する response オブジェクト返さなければいけません。 与えられた responseresponse.template_nameresponse.context_data を変更することができますが、 全くあたらしい SimpleTemplateResponse か同等のものを 作成することも可能です。

process_template_response() は response インスタンスが render() メソッド を持っている時、つまりそのresponse が TemplateResponse クラス、あるいは同等のクラス であるのみ呼び出されます。

明示的にresponseをレンダする必要はありません。 – 全てのテンプレート応答ミドルウェア が呼び出された時に1度だけ自動的にresponseがレンダされます。

応答フェーズの間、ミドルウェアは逆順で実行されます。 process_template_response もそれに含まれます。

process_response

process_response(self, request, response)

requestHttpRequest オブジェクトです。 response は Django のビュー関数の返す HttpResponse オブジェクトです。

process_response()HttpResponse オブジェクトを 返さねばなりません。渡された response オブジェクトを変更して返しても良いですし、 新たに HttpResponse オブジェクトを生成して返すことも可能です。

process_request()process_view() メソッドとは異なって、 process_response() メソッドは必ず呼ばれます。 同じミドルウェアクラスの process_request()process_view() メソッド がスキップされても呼ばれます。これより先に呼ばれるミドルウェアメソッドが httpresponse クラスを返していたからです(つまり、例えば process_response() メソッドは process_request() でセットアップが 完了していることを前提としてはいけない、ということです。) さらに、レスポンスフェーズの間はクラスは逆順、つまり下から上に適用されます。 これは MIDDLEWARE_CLASSES の最後に定義されたクラスが最初に 実行されるという意味です。

process_exception

process_exception(self, request, exception)

requestHttpRequest オブジェクトです。 exception はビュー関数の送出した Exception オブジェクトです。

Django はビューが例外を送出した際に process_exception() を呼び出します。 process_exception()None または HttpResponse オブジェクトのいずれかを返さねばなりませ ん。 HttpResponse オブジェクトを返した場合、その応答 をそのままブラウザに返します。それ以外の場合、デフォルトの例外処理を起動し ます。

ここでも応答フェーズの間はミドルウエアは逆順で実行されます。 process_exception もそれに含まれます。 もしも例外ミドルウェアが応答を返すのであれば、 そのミドルウェアより上位にあるミドルウェアクラスは決して呼ばれることはありません。

__init__

ほとんどのミドルウェアクラスは、実質的に単なる process_* メソッドの置き 場でしかないので、初期化メソッドは必要ありません。ミドルウェアのグローバル な状態を保存するのに __init__ メソッドを使ってもかまいませんが、以下の 点に注意してください:

  • Django はミドルウェアクラスを引数なしで初期化するので、 __init__ には必須の引数を定義できません。
  • process_* メソッドはリクエストごとに呼び出されますが、 __init__ は Web サーバの起動時に 一度 しか呼び出されません。

ミドルウェアを動的に有効にする

ミドルウェアを使うかどうかを実行時に決められると便利なことがあります。ミド ルウェアの __init__ メソッドで django.core.exceptions.MiddlewareNotUsed を送出すると、 Django はそ のミドルウェアを処理から外します。

ガイドライン

  • ミドルウェアのクラスはサブクラスでなくてもかまいません。
  • ミドルウェアのクラスはPython のモジュールパス上のどこにでも置けます。 Django にとって必要なのは MIDDLEWARE_CLASSES にクラスへの パスが指定されていることだけです。
  • Django で使えるミドルウェア を参考にしてく ださい。
  • 自分の書いたミドルウェアコンポーネントが他の人にとっても有用だと思っ たなら、ぜひ コミュニティにコントリビュート してください!知らせてくだされば、 Django に追加するか検討します。