Django ミドルウェア

Django ミドルウェア
目次
  • Django ミドルウェア
  • カスタム ミドルウェア
  • process_request
  • process_response
  • process_view
  • process_exception
  • process_template_response (あまり使用されない)
  • ミドルウェア版ログイン検証
  • Django リクエスト フロー図

カスタム ミドルウェア

カスタム ミドルウェアには5つのメソッドを定義できます。主なものはprocess_requestとprocess_responseです。

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

これらのメソッドの戻り値はNoneまたはHttpResponseオブジェクトです。Noneの場合、通常のフローが続き、次のミドルウェアが処理されます。HttpResponseオブジェクトの場合、直接ユーザーに返されます。

ミドルウェアはDjangoのリクエストとレスポンスを処理するためのフレームワーク レベルのフックです。基本的に、ミドルウェアはクラスです。

4つの特徴に注意します:実行時、実行順序、パラメータ、戻り値。

カスタム ミドルウェアの例

from django.utils.deprecation import MiddlewareMixin

class CustomMiddleware1(MiddlewareMixin):
    def process_request(self, request):
        print("CustomMiddleware1のprocess_requestを実行")

    def process_response(self, request, response):
        print("CustomMiddleware1のprocess_responseを実行")
        return response

process_request

process_requestの引数はrequestです。これはビュー関数と同じrequestオブジェクトです。
戻り値はNoneまたはHttpResponseオブジェクトです。Noneの場合、通常のフローが続き、ビュー関数が実行されます。
HttpResponseオブジェクトの場合、ビュー関数は実行されず、直接レスポンスが返されます。

複数のミドルウェアを配置した場合、Djangoは以下のようにprocess_requestメソッドを実行します。

from django.utils.deprecation import MiddlewareMixin

class CustomMiddleware1(MiddlewareMixin):
    def process_request(self, request):
        print("CustomMiddleware1のprocess_requestを実行")

class CustomMiddleware2(MiddlewareMixin):
    def process_request(self, request):
        print("CustomMiddleware2のprocess_requestを実行")

settings.pyのMIDDLEWARE設定に上記の2つのカスタム ミドルウェアを登録します。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'middlewares.CustomMiddleware2',
    'middlewares.CustomMiddleware1',
]

ビュー関数をアクセスすると、ターミナルに以下のような出力が表示されます。

CustomMiddleware2のprocess_requestを実行
CustomMiddleware1のprocess_requestを実行
app01のindexビュー関数を実行

process_requestメソッドはビュー関数の前に実行されます。複数のミドルウェアを配置した場合、MIDDLEWAREリストの順序に従って実行されます。異なるミドルウェア間で共有されるrequestは同じオブジェクトです。

process_response

process_responseの引数はrequestとresponseです。
requestはビュー関数と同じオブジェクトです。
responseはビュー関数から返されたHttpResponseオブジェクトです。
戻り値はHttpResponseオブジェクトでなければなりません。

上記のCustomMiddleware1とCustomMiddleware2にprocess_responseメソッドを追加します。

class CustomMiddleware1(MiddlewareMixin):
    def process_request(self, request):
        print("CustomMiddleware1のprocess_requestを実行")
    def process_response(self, request, response):
        print("CustomMiddleware1のprocess_responseを実行")
        return response

class CustomMiddleware2(MiddlewareMixin):
    def process_request(self, request):
        print("CustomMiddleware2のprocess_requestを実行")
    def process_response(self, request, response):
        print("CustomMiddleware2のprocess_responseを実行")
        return response

ビュー関数をアクセスすると、ターミナルに以下のような出力が表示されます。

CustomMiddleware2のprocess_requestを実行
CustomMiddleware1のprocess_requestを実行
app01のindexビュー関数を実行
CustomMiddleware1のprocess_responseを実行
CustomMiddleware2のprocess_responseを実行

process_responseメソッドはビュー関数の後に実行されます。複数のミドルウェアを配置した場合、MIDDLEWAREリストの順序に逆順で実行されます。

process_view

process_viewの引数はrequest、view_func、view_args、view_kwargsです。
requestはHttpRequestオブジェクトです。
view_funcはDjangoが使用するビュー関数です。
view_argsはビュー関数に渡される位置引数のリストです。
view_kwargsはビュー関数に渡されるキーワード引数の辞書です。
Djangoはビュー関数を実行する前にprocess_viewメソッドを呼び出します。
戻り値はNoneまたはHttpResponseオブジェクトです。

CustomMiddleware1とCustomMiddleware2にprocess_viewメソッドを追加します。

class CustomMiddleware1(MiddlewareMixin):
    def process_request(self, request):
        print("CustomMiddleware1のprocess_requestを実行")
    def process_response(self, request, response):
        print("CustomMiddleware1のprocess_responseを実行")
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("CustomMiddleware1のprocess_viewを実行")
        print(view_func, view_func.__name__)

class CustomMiddleware2(MiddlewareMixin):
    def process_request(self, request):
        print("CustomMiddleware2のprocess_requestを実行")
    def process_response(self, request, response):
        print("CustomMiddleware2のprocess_responseを実行")
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("CustomMiddleware2のprocess_viewを実行")
        print(view_func, view_func.__name__)

ビュー関数をアクセスすると、ターミナルに以下のような出力が表示されます。

CustomMiddleware2のprocess_requestを実行
CustomMiddleware1のprocess_requestを実行
--------------------------------------------------------
CustomMiddleware2のprocess_viewを実行
<function index at 0x...> index
--------------------------------------------------------
CustomMiddleware1のprocess_viewを実行
<function index at 0x...> index
app01のindexビュー関数を実行

process_viewメソッドはprocess_requestの後に、ビュー関数の前に実行されます。実行順序はMIDDLEWAREリストの順序に従って実行されます。

process_exception

process_exceptionの引数はrequestとexceptionです。
requestはHttpRequestオブジェクトです。
exceptionはビュー関数で発生した例外です。
戻り値はNoneまたはHttpResponseオブジェクトです。

ビュー関数で例外を発生させる例:

def index(request):
    print("app01のindexビュー関数を実行")
    raise ValueError("エラー発生")
    return HttpResponse("OK")

CustomMiddleware1にprocess_exceptionメソッドを追加します。

class CustomMiddleware1(MiddlewareMixin):
    def process_request(self, request):
        print("CustomMiddleware1のprocess_requestを実行")
    def process_response(self, request, response):
        print("CustomMiddleware1のprocess_responseを実行")
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("CustomMiddleware1のprocess_viewを実行")
        print(view_func, view_func.__name__)
    def process_exception(self, request, exception):
        print("例外発生:", exception)
        print("CustomMiddleware1のprocess_exceptionを実行")
        return HttpResponse(str(exception))

ビュー関数をアクセスすると、ターミナルに以下のような出力が表示されます。

CustomMiddleware2のprocess_requestを実行
CustomMiddleware1のprocess_requestを実行
--------------------------------------------------------
CustomMiddleware2のprocess_viewを実行
<function index at 0x...> index
--------------------------------------------------------
CustomMiddleware1のprocess_viewを実行
<function index at 0x...> index
app01のindexビュー関数を実行
例外発生: ValueError("エラー発生")
CustomMiddleware1のprocess_exceptionを実行
CustomMiddleware1のprocess_responseを実行
CustomMiddleware2のprocess_responseを実行

process_template_response (あまり使用されない)

process_template_responseの引数はrequestとresponseです。
responseはTemplateResponseオブジェクトです。
Djangoはビュー関数を実行した後にprocess_template_responseメソッドを呼び出します。
戻り値はHttpResponseオブジェクトでなければなりません。

ミドルウェア版ログイン検証

ログイン検証はセッションを使用します。したがって、データベースにdjango_sessionテーブルが必要です。

ビュー関数の例:

def login(request):
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")
        if user == "admin" and pwd == "admin123":
            request.session["user"] = user
            next_url = request.GET.get("next")
            if next_url:
                return redirect(next_url)
            else:
                return redirect("/index/")
    return render(request, "login.html")

Django リクエスト フロー図

タグ: Django ミドルウェア process_request process_response process_exception

7月7日 22:50 投稿