middleware がどう動くか実装をみる
前回セッションのバックエンド実装について書いた。
実際に使うときは、ミドルウェアで指定する必要がある。
Django のミドルウェアは公式ドキュメントによると object を継承したクラスをかけばいいという。自分もちょっとだけ書いたことがある。ただこのとき、固定されたメソッド名をどう拾って処理できるようにしているか、あと object を継承していてどこから定義したものがつかえるのかよくわからなかった。
参考
おさらい
設定する
MIDDLEWARE_CLASSES
でタブル内に文字列でクラスのパスを指定する。
Middleware | Django documentation | Django
実装する
先ほどの SessionMiddleware
の場合こうなっている
django/middleware.py at master · django/django · GitHub
Python の object を継承したクラスをつくる。あと必要なメソッドを実装すればOK。 Middleware | Django documentation | Django によると以下の5つ
- process_request
- process_view
- process_exception
- process_template_response
- process_response
SessionMiddleware
の場合、 Django 読み込み時に backend のエンジンを読み込み、 SessionStore
クラスのインスタンスを保持しておく。 リクエストが来たら都度 SessionStore
のインスタンスを作成、レスポンスを返すときにもろもろの処理をはさんでいる。
実装をみる
実装がどこにあるか
実装を調べようにも SessionMiddleware
は MIDDLEWARE_CLASSES
で読み込むよう定義しているだけ。なので、 MIDDLEWARE_CLASSES
そのものを検索する。すると、 django.core.handlers.base
でなにか処理していることがわかる。
django/base.py at master · django/django · GitHub
BaseHandler
BaseHandler
クラスでやってることの大枠はたぶんこう
- init
- load_middleware
- get_response
初期化時に process_xxx
のメソッドに対応する変数を初期化しておく。
継承先の __call__
で呼ばれる load_middleware
で MIDDLEWARE_CLASSES
で定義したミドルウェアを取り出し、ミドルウェアのインスタンスの属性に process_xxx
があれば追加しておく。
レスポンスを返すときにフックポイントにきたら先ほど登録したミドルウェアを取り出して実行する。
WSGIHandler
先ほどの BaseHandler
クラスを使っているのが WSGIHandler
。 __call__
されたらレスポンスを返す。どこかで while True: のようなループがあって、そこでインスタンスになっているものが待ち受けている?
django/wsgi.py at master · django/django · GitHub
使われているところを探すと、 django.core.wsgi#get_wsgi_application
で使われていることがわかった。これは django.setup()
して return WSGIServer
するだけの関数のようだった。これは django-admin.py startproject proj
したときに生成される wsgi.py
で使われている。gunicorn などで動かすときに使う。
おわりに
- 文字列で指定したクラスを import する
- middleware から固定のメソッド名を探して格納、フック時に適用する
というような話だった。
次は余力があれば runserver か render あたりをかく。