DjangoでMiddlewareを自作する方法

はじめに

こんにちは、サイオステクノロジーのあさりです。今回はDjangoのミドルウェアを自作する方法についてまとめてみました。ミドルウェアは、Djangoのすべてのリクエスト・レスポンス処理にフックを加えるためのフレームワークで、サイト全体に何らかの機能を追加したい場合に利用します。

環境

  • Python3
  • Django4.2

ミドルウェアの自作方法

ミドルウェアを自作するには、以下のような__init__()メソッドと__call__()メソッドを持つクラスを実装します。

#custom_middleware.py

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
    
        # (1)リクエストへの前処理
        
        response = self.get_response(request)
        
        # (2)レスポンスへの後処理

        return response

ビューが呼び出される前にrequestに前処理を加えたい場合は(1)の部分に処理を記述し、ビュー呼び出し後にresponseに後処理を加えたい場合は(2)の部分に処理を記述します。

作成したミドルウェアを有効にするためには設定ファイルで有効とするミドルウェアを定義しているMIDDLEWAREに追加する必要があります。Djangoプロジェクトを作成したときに自動生成される設定ファイル(settings.py)では、次の7つのミドルウェアが有効となっています。

#settings.py

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',
    # ここに自作ミドルウェアを追加
]

各ミドルウェアの役割やその他の便利なミドルウェアについては、こちらを参考にしてください。自作のミドルウェアを有効にするためには、ここに自作したミドルウェアを追加します。この際、リクエストの前処理は記載された上から順番にレスポンスの後処理は下から順番に実行されることに注意してください。記載する順番を間違えると正常に動作しないこともあるため、処理内容にもよりますが、自作したミドルウェアは一番に下に追加するのがよいと思います。

ミドルウェアの自作例

自作例として、今回はアクセスログの記録をミドルウェアを使って実装したいと思います。記録する内容としては以下の3点とします。

  • アクセス日時
  • リクエストURL
  • リクエストメソッド

アプリケーション作成

はじめに、次のコマンドを実行してaccesslogというアプリケーションを作成します。

python manage.py startapp accesslog

作成したアプリケーションをプロジェクトに登録するために設定ファイルのINSTALLED_APPSの末尾にaccesslogを追加します。

# settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'accesslog', 
]

モデル定義

次に、accesslog/models.pyを次のように編集し、アクセスログのモデルクラスを定義します。

# accesslog/models.py

from django.db import models

#アクセスログモデル定義
class AccessLog(models.Model):
	class Meta:
		db_table = 'access_log'
		verbose_name = verbose_name_plural = 'アクセスログ'

	access_date_time = models.DateTimeField(verbose_name='アクセス日時', auto_now_add=True)
	request_url = models.CharField(verbose_name='リクエストURL', max_length=2083)
	request_method = models.CharField(verbose_name='リクエストメソッド', max_length=7)

アクセス日時については、auto_now_addをTrueに設定しています。これにより新たにオブジェクトが追加されるときに自動で現在日時が設定されるようになります。モデルの定義が完了したら、次のコマンドを実行してモデルをデータベースに反映させましょう。

python manage.py makemigrations
python manage.py migrate

ミドルウェア実装

テーブルの作成まで完了したので、ここからミドルウェアの実装をしていきます。まず、プロジェクト直下にmiddlewareディレクトリを作成し、accesslog_middleware.pyを作成します(今回はアクセスログのミドルウェアということでこの命名としましたが、ディレクトリ名・ファイル名共にに決まりはありません。)

それでは、accesslog_middleware.pyの中身を書いていきます。

# middleware/accesslog_middleware.py

from accesslog.models import AccessLog

class AccessLogMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
		    AccessLog(
            request_url=request.path,
            request_method=request.method,
        ).save()
        
        response = self.get_response(request)

        return response

このミドルウェアでは、全てのリクエストに対して、pathとmethodを取得して新たなAccessLogオブジェクトを保存しています。それでは、設定ファイルのMIDDLEWAREにこのミドルウェアを末尾に追加して有効化しましょう。

#settings.py

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',
    'middleware.accesslog_middleware.AccessLogMiddleware',   #自作ミドルウェアを追加
]

ここまで完了したら、サイトにアクセスしてみてaccess_logテーブルに実際にアクセスログが記録されていることを確かめてみてください。

おわりに

今回は、DjangoのMiddlewareの実装方法を紹介しました。ミドルウェアは、Djangoのすべてのリクエスト・レスポンス処理にフックを加えるためのフレームワークで、各アプリケーションのビュー関数で重複する処理がある場合、ミドルウェアでその処理を共通化することができます。便利な機能なのでぜひ使ってみてください。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です