Django: ミドルウェアの実装方法(全てのビューに処理をフックする方法)

2010/03/23

Djangoでは、アプリ、context_processorsなど様々なプラグイン機能が提供されており、画一的なフレームワークの中でソフトウェアを実装することで効率化・高可搬性を実現しています。

しかし、一旦システムを実装開始すると、システムは様々な環境が依存しあうもので、一つの関数を書き換えると様々なビューやテンプレートファイルに修正範囲が波及する。。。なんてことがよく起こります。

せっかくMVCフレームワークを提供しているのに、それを正しく使わないのが悪い!などと怒られそうですが、理想と現実は異なる訳で、プラットフォームにはそのどちらもフォローできる柔軟な環境が求められます。

既存のシステム全てに共通で処理をフックしたり、テンプレート変数を追加したい。。。などということを実現するにはどうしたら良いのでしょうか?

これを簡単に実現できる方法がDjangoにはあります。
それがミドルウェアです。

ミドルウェアは大まかに言うと、 ビューをコールする直前と直後にフックを入れることができる機能 です。従って、全てのビューにある特定のテンプレート変数を追加・変更したり、共通の処理を追加することが可能です。

ミドルウェアを追加する場合、

  1. ミドルウェアクラスを新規作成
  2. ミドルウェアクラスをsettings.pyに登録

といった手順を経る必要があります。

まずはsettings.pyにミドルウェアを登録しましょう。

    $ emacs settings.py
      ...
      MIDDLEWARE_CLASSES = (
         ...,
         'hoge_app.middlewares.hookfunc',
      )

次に、実態 hookfunc クラスを実装します。

    $ emacs hoge_app/middlewares.py
    class hookfunc():
       def __init__(self):
          pass
       def process_request(self, request):
          """
	  どのviewを実行するか決定する前にコールされるフック。
	  """
          return None		# 処理継続
	  # return request	# ここで処理終了
       def process_view(self, request, view_func, view_args, view_kwargs):
          """
	  実行されるviewが決定した後にコールされるフック。
	  """
	  return None		# 処理継続
          # return response	# ここで処理終了
       def process_response(self, request, response):
          """
	  viewを実行した後に呼びだされるフック。
	  """
          return response	# ここで処理終了

ミドルウェアクラスでは、予めI/Fとして定義されている

  • process_request(self, request)
  • process_view(self, request, view_func, view_args, view_kwargs)
  • process_response(self, request, response)

をオーバーライドすることで、実行されるタイミングが決定されます。

また、返り値としてNoneを返すと次のミドルウェアクラスのハンドラを実行し、
requestオブジェクトやresponseオブジェクトを返すと、そこで処理が完了するといった処理を実現することも可能です。

blog comments powered by Disqus
カテゴリー