# Django 5.0.9.dev20240806133106 ドキュメント

# ミドルウェア (Middleware)

ミドルウェアは、Django のリクエスト/レスポンス処理にフックを加えるためのフレームワークです。これは、Django の入力あるいは出力をグローバルに置き換えるための、軽量で低レベルの「プラグイン」システムです。

各ミドルウェアのコンポーネントは、それぞれある特定の機能を実行する役目を持っています。たとえば、Django には `AuthenticationMiddleware` というミドルウェアコンポーネントがあります。このミドルウェアは、セッションを利用して、リクエストとユーザーとを関連付けます。

このドキュメントでは、ミドルウェアが機能するしくみ、ミドルウェアを有効にする方法、そして、自分でミドルウェアを書く方法について説明します。Django には組み込みのミドルウェアがいくつか用意されているので、自分で書かなくてもすぐに使い始めることができます。これらの組み込みのミドルウェアについては、組み込みミドルウェアリファレンス にドキュメントされているので参照してください。

## 自分でミドルウェアを書く

ミドルウェアファクトリは、ミドルウェアを返す `get_response` を取る呼び出し可能なオブジェクトです。ミドルウェアは (ビューと同じように) リクエストを受け取ってレスポンスを返す呼び出し可能なオブジェクトです。

ミドルウェアは、以下のように関数として書くことができます:

    def simple_middleware(get_response):
        # One-time configuration and initialization.

        def middleware(request):
            # Code to be executed for each request before
            # the view (and later middleware) are called.

            response = get_response(request)

            # Code to be executed for each request/response after
            # the view is called.

            return response

        return middleware

もしくは、インスタンスを呼び出し可能なクラスとして書くこともできます:

    class SimpleMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
            # One-time configuration and initialization.

        def __call__(self, request):
            # Code to be executed for each request before
            # the view (and later middleware) are called.

            response = self.get_response(request)

            # Code to be executed for each request/response after
            # the view is called.

            return response

Django によって渡される `get_response` 呼び出し可能オブジェクトは、実際の (これがミドルウェアの最後にリストアップされている場合) ビューか、チェーン内の次のミドルウェアの可能性があります。現在のミドルウェアはこれが何かを知る必要も気にする必要もなく、ただ次に来るものを表します。

上記は、わずかに単純化したものです -- チェーン内の際にリストアップされたミドルウェアに対する `get_response` は実際のビューではなく ビューミドルウェア を適用する処理を行うハンドラからのラッパーメソッドです。これは適切な URL 属性でビューを呼び出し、テンプレートレスポンス と 例外 を適用します。

ミドルウェアは同期 Python のみ(デフォルト)、非同期 Python のみ、または両方をサポートできます。どのようなリクエストをサポートするのか、またどのようなリクエストを受け取るのかについての詳細は 非同期サポート を参照してください。

ミドルウェアは、あなたの Ptyhon パスのどこでも使うことができます。

### `__init__(get_response)`

ミドルウェアファクトリは `get_response` 引数を受け取る必要があります。ミドルウェアに対してグローバルな宣言を初期化することもできます。いくつかの注意事項があります:

- Django は `get_response` 引数でミドルウェアを初期化するため、`__init__()` で他の引数を必須にすることはできません。
- リクエストごとに 1 回呼ばれる `__call__()` メソッドとは異なり、`__init__()` はウェブサーバが起動したときに 1回だけ 呼ばれます。

### ミドルウェアを不使用としてマークする

起動時にミドルウェアを使うかどうかを決めることは、ときに有用です。この場合、ミドルウェアの `__init__()` メソッドが `MiddlewareNotUsed` を投げる可能性があります。Django はミドルウェアプロセスからこのミドルウェアを削除し、`DEBUG` が `True` のときはデバッグメッセージを django.request ロガーに記録します。

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

ミドルウェア要素をアクティブ化するには、Django の設定内の `MIDDLEWARE` リストに追加してください。

`MIDDLEWARE` では、各ミドルウェア要素は文字列で表されます: ミドルウェアファクトリのクラスや関数名に対する完全な Python パスです。 例えば、以下は `django-admin startproject` で生成されるデフォルト値です:

    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",
    ]

Django の導入では、ミドルウェアは必須ではありません — お望みならば `MIDDLEWARE` は空でも構いません — しかし、最低でも `CommonMiddleware` を使うことを強くお勧めします。

ミドルウェアは他のミドルウェアに依存するため、`MIDDLEWARE` の順番は重要です。`AuthenticationMiddleware` はセッション内に認証済みユーザを保持します。したがって、`SessionMiddleware` の後に起動する必要があります。Django のミドルウェアクラスの順番については、Middleware の順序 を参照してください。

## ミドルウェアの順番とレイヤ

ビューを呼び出す前、リクエストの段階で、Django は `MIDDLEWARE` 内で定義された順番で上から下に向かってミドルウェアを適用します。

これはタマネギのように考えることができます: 各ミドルウェアクラスは、タマネギの中心にあるビューをラップする "レイヤ" です。リクエストがタマネギのすべてのレイヤ (つまり中心にあるビューにいたる全ての道) を通過すると (各レイヤーは `get_response` を呼び出してリクエストを次のレイヤに渡します)、レスポンスは各レイヤーを (逆順で) 通過して戻ります。

いずれかのレイヤが短絡し、`get_response` を呼び出さずにレスポンスを返すことを決定した場合、そのレイヤの内側にあるタマネギの (ビューを含む) レイヤはリクエストおよびレスポンスを受け取りません。 レスポンスは、リクエストが通過したのと同じレイヤーを介してのみ返されます。

## 他のミドルウェアのフック

上述した基本的なリクエストやレスポンスのミドルウェアパターンのほかに、3 つの特殊なメソッドをクラスベースのミドルウェアに追加できます:

### `process_view()`

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

`request` は `HttpRequest` クラスのオブジェクトです。`view_func` は、直後に Django が使用する Python の関数です (関数の名前の文字列ではなく、実際の関数オブジェクトです)。`view_args` はビューに渡される位置引数のリスト、`view_kwargs` はビューに渡されるキーワード引数のディクショナリです。`view_args` も `view_kwargs` も、第一引数 (`request`) を含んでいません。

`process_view()` は、Django がビューを呼び出す直前に呼び出されます。

`None` もしくは `HttpResponse` オブジェクトを返す必要があります。`None` を返す場合、Django はこのリクエストの処理を続け、他のすべての `process_view()` ミドルウェアを実行し、さらに適切なビューを実行します。`HttpResponse` オブジェクトを返す場合、Django はわざわざ適切なビューを呼び出すことはしません; レスポンスミドルウェアを `HttpResponse` に適用し、結果を返します。

注釈

ビューが実行される、ミドルウェアの内側もしくは `process_view()` 内の `request.POST` にアクセスすると、ミドルウェアの後に実行される全てのビューが リクエストに対するアップロードハンドラを修正する ことができなくなるため、通常は避けられるべきです。

`CsrfViewMiddleware` クラスだけは例外と考えていいでしょう。というのも、このミドルウェアには、`csrf_exempt()` と `csrf_protect()` というデコレータが用意されていて、このデコレータを使えば、CSRF の検証が必要になったどの時点でも、明示的にビューを制御できるからです。

### `process_exception()`

`process_exception`(request, exception)

`request` は `HttpRequest` オブジェクトです。`exception` は、ビュー関数から投げられた `Exception` オブジェクトです。

Django は、ビューが例外を起こした時に `process_exception()` を呼び出します。`process_exception()` は `None` あるいは `HttpResponse` オブジェクトを返さなければなりません。 `HttpResponse` オブジェクトを返した場合、テンプレートレスポンスミドルウェアおよびレスポンスミドルウェアが適用され、その結果得られたレスポンスがブラウザに返されます。そうでなければ、 デフォルトの例外のハンドリング が行われます。

繰り返しますが、ミドルウェアは `process_exception` を含むレスポンスフェーズで逆順に実行されます。例外ミドルウェアがレスポンスを返した場合、そのミドルウェアの上のミドルウェアクラスの `process_exception` メソッドは全く呼び出されません。

### `process_template_response()`

`process_template_response`(request, response)

`request` は `HttpRequest` クラスのオブジェクトです。`response` は、Django のビューまたはミドルウェアから返される、`TemplateResponse` クラスのオブジェクト (あるいはそれと同等なもの) です。

`process_template_response()` は、レスポンスオブジェクトが `render()` メソッドを持っている場合、つまり、`TemplateResponse` クラスのオブジェクトあるいはそれと同等のものである場合に、ビューの実行の直後に呼ばれます。

このメソッドは、`render` メソッドを実装したレスポンスオブジェクトでなければなりません。このメソッド内では、与えられた `response` に対して `response.template_name` や `response.context_data` を修正したり、あるいは、新規に `TemplateResponse` クラスのオブジェクト (あるいはそれと同等なもの) を作成したりすることができます。

ただし、レスポンスを自分でレンダリング (render) する必要はありません。なぜなら、レスポンスオブジェクトは、すべてのテンプレートレスポンスミドルウェアが呼び出された後に、自動的にレンダリングされるからです。

レスポンスフェーズでは、ミドルウェアは逆順に呼び出されます。これには、`process_template_response()` も含まれます。

## ストリーミングレスポンス (streaming responses) を扱う

`HttpResponse` とは違い、`StreamingHttpResponse` は `content` 属性を持ちません。そのため、ミドルウェアはもはや、すべてのレスポンスが `content` 属性を持っていることを前提にすることができなくなります。したがって、content にアクセスする必要がある場合には、レスポンスオブジェクトがストリーミングレスポンスオブジェクトかどうかをチェックし、その結果によって処理を場合分けしなければなりません。

    if response.streaming:
        response.streaming_content = wrap_streaming_content(response.streaming_content)
    else:
        response.content = alter_content(response.content)

注釈

`streaming_content` はメモリ上に置けないくらい大きいと想定しておくべきです。レスポンスミドルウェアでは、これを新しいジェネレータでラップできます。しかし、このジェネレータを処理することがあってはなりません。典型的なラップの方法は、次のようになります。

    def wrap_streaming_content(content):
        for chunk in content:
            yield alter_content(chunk)

`StreamingHttpResponse` は同期イテレータと非同期イテレータの両方を受け付けます。ラッピング関数は一致する必要があります。ミドルウェアがこの種のイテレータをサポートする必要がある場合には、`StreamingHttpResponse.is_async` 確認してください。

Changed in Django 4.2:

非同期イテレータを使用したストリーミングレスポンスのサポートが追加されました。

## 例外のハンドリング

Django はビューまたはミドルウェアによって起こされた例外を、エラーステータスコードを持つ適切な HTTP レスポンスに自動的に変換します。特定の例外 は 4xx ステータスコードに変換されますが、未知の例外は 500 ステータスコードに変換されます。

この変換は各ミドルウェアの前と後で行われます (玉ねぎの各層の間にある薄い皮のようなものとして考えられます)。そのため、すべてのミドルウェアは常に、呼び出し可能な `get_response` の呼び出しから返ってきたある種の HTTP レスポンスを取得することに依存しています。ミドルウェアは、`get_response` への呼び出しを `try/except` の中にラッピングしたり、後ろのミドルウェアまたはビューから発生する可能性のある例外を心配したり必要はありません。たとえ呼び出しチェーンのすぐ次のミドルウェアがたとえば `Http404` 例外を発生させたとしても、ミドルウェアがその例外を見ることはなく、代わりに得るのは 404 の `status_code` を持つ `HttpResponse` オブジェクトです。

この変換をスキップして例外を上に伝搬するには、`DEBUG_PROPAGATE_EXCEPTIONS` を `True` に設定できます。

## 非同期サポート

ミドルウェアは同期リクエストと非同期リクエストのどのような組み合わせでもサポートできます。ミドルウェアが両方をサポートできない場合、Django はリクエストをミドルウェアの要求に合うように適応させますが、パフォーマンス上は不利になります。

デフォルトでは、Django はミドルウェアが同期リクエストのみを処理できると想定します。この前提を変更するには、ミドルウェア ファクトリ関数またはクラスに次の属性を設定します。

- `sync_capable` は、ミドルウェアが同期リクエストを処理できるかどうかを表すブール値です。デフォルトは `True`。
- `async_capable` は、ミドルウェアが非同期リクエストを処理できるかどうかを表すブール値です。デフォルトは `False`。

ミドルウェアが `sync_capable = True` と `async_capable = True` の両方を持っている場合、Django はそれを変換せずにリクエストに渡します。この場合、ミドルウェアが非同期リクエストを受け取ったかどうかは、渡された `get_response` オブジェクトがコルーチン関数かどうかを `asgiref.sync.iscoroutinefunction` で確認できます。

`django.utils.decorators` モジュールには、ミドルウェアのファクトリ関数にこれらのフラグを設定できる `sync_only_middleware()`、`async_only_middleware()`、`sync_and_async_middleware()` デコレータが含まれています。

返された callable は、`get_response` メソッドの同期または非同期の性質と一致していなければなりません。非同期の `get_response` がある場合、コルーチン関数 (`async def`) を返さなければなりません。

`process_view`、`process_template_response`、`process_exception` メソッドは、もし提供された場合、同期/非同期モードにも一致するように適応する必要があります。ただし、適応させなかった場合でも Django は必要に応じてそれらを個別に調整させますが、パフォーマンスがさらに低下します。

以下は、両方をサポートするミドルウェア関数の作成方法の例です。

    from asgiref.sync import iscoroutinefunction
    from django.utils.decorators import sync_and_async_middleware

    @sync_and_async_middleware
    def simple_middleware(get_response):
        # One-time configuration and initialization goes here.
        if iscoroutinefunction(get_response):

            async def middleware(request):
                # Do something here!
                response = await get_response(request)
                return response

        else:

            def middleware(request):
                # Do something here!
                response = get_response(request)
                return response

        return middleware

注釈

同期呼び出しと非同期呼び出しの両方をサポートするハイブリッド ミドルウェアを宣言する場合、得られる呼び出しの種類が基になるビューと一致しなくなる可能性があります。Django は同期/非同期の遷移ができる限り少なくなるように、ミドルウェアのコールスタックを最適化します。

よって、たとえ非同期ビューをラップしている場合でも、ビューとの間に他の同期ミドルウェアが存在する場合、同期モードで呼び出される可能性があります。

非同期のクラスベースのミドルウェアを使用する場合は、次のようにしてインスタンスが正しくコルーチン関数としてマークされていることを確認する必要があります。

    from asgiref.sync import iscoroutinefunction, markcoroutinefunction

    class AsyncMiddleware:
        async_capable = True
        sync_capable = False

        def __init__(self, get_response):
            self.get_response = get_response
            if iscoroutinefunction(self.get_response):
                markcoroutinefunction(self)

        async def __call__(self, request):
            response = await self.get_response(request)
            # Some logic ...
            return response

## Django 1.10 以前のスタイルのミドルウェアをアップグレードする

class `django.utils.deprecation.``MiddlewareMixin`

Django は `django.utils.deprecation.MiddlewareMixin` を提供しています。これを使うと、`MIDDLEWARE` と古い `MIDDLEWARE_CLASSES` 両方に互換性があり、同期リクエストと非同期リクエストの両方をサポートするミドルウェアクラスの作成が簡単になります。Django に含まれるすべてのミドルウェアクラスは、両方の設定と互換性があります。

mixin は `__init__()` メソッドを提供しています。これは、必須の `get_response` 引数を受け取って `self.get_response` に保持します。

`__call__()` メソッド:

1. (定義されている場合) `self.process_request(request)` を呼び出します。
2. `self.get_response(request)` を呼び出し、後のミドルウェアとビューからレスポンスを得ます。
3. (定義されている場合) `self.process_response(request, response)` を呼び出します。
4. レスポンスを返します。

`MIDDLEWARE_CLASSES` で使われている場合は、`__call__()` メソッドは決して使われません; Django は `process_request()` と `process_response()` を直接呼び出します。

ほとんどの場合、この mixin を継承することで、旧式のミドルウェアと十分な下位互換性を持つ新しいシステムと互換性を持たせることができます。 新しい短絡セマンティクスは無害であり、既存のミドルウェアにとっても有益です。 いくつかのケースでは、ミドルウェアクラスは新しいセマンティクスに調整するためにいくつかの変更を必要とすることがあります。

`MIDDLEWARE` と `MIDDLEWARE_CLASSES` の動作には以下のような違いがあります。

1. `MIDDLEWARE_CLASSES` のもとでは、全てのミドルウェアは常にその `process_response` メソッドが呼び出されます。たとえその前のミドルウェアが `process_request` メソッドからレスポンスを返してショート（短絡）した場合でもです。 `MIDDLEWARE` のもとでは、ミドルウェアはオニオンのように動作します。レスポンスが外に出るときに通過するレイヤーは、リクエストが入るときに見たのと同じレイヤーです。ミドルウェアがショートした場合、そのミドルウェアとそれより前にある `MIDDLEWARE` のミドルウェアのみがレスポンスを見ることになります。
2. `MIDDLEWARE_CLASSES` のもとでは、ミドルウェアの `process_request` メソッドから発生した例外に `process_exception` が適用されます。 `MIDDLEWARE` のもとでは、 `process_exception` はビュー（または `TemplateResponse` の `render` メソッド）から発生した例外にのみ適用されます。ミドルウェアから発生した例外は適切な HTTP レスポンスに変換され、次のミドルウェアに渡されます。
3. `MIDDLEWARE_CLASSES` のもとでは、もし `process_response` メソッドが例外を発生させた場合、それ以前の全てのミドルウェアの `process_response` メソッドはスキップされ、常に `500 Internal Server Error` HTTP レスポンスが返されます（たとえ発生した例外がたとえば `Http404` だったとしてもです）。 `MIDDLEWARE` のもとでは、ミドルウェアから例外が発生した場合、直ちに適切な HTTP レスポンスに変換され、次のミドルウェアがそのレスポンスを見ることになります。ミドルウェアが例外を発生させたことを理由にミドルウェアがスキップされることはありません。