LoginSignup
1

More than 3 years have passed since last update.

DjangoのMiddlewareを自作してどこからでもrequest情報にアクセスできるようにしてみた

Last updated at Posted at 2020-03-10

modelのuser_created(作成者)やuser_updated(更新者)に共通処理でログインユーザを格納できないか考え始めたのがきっかけ。

それまではviewからformにユーザ情報を渡して、user_createdやuser_updatedに格納する処理を書いてました。

Djangoのmiddleware(ミドルウェア)とは

公式より

ミドルウェアは、Django のリクエスト/レスポンス処理にフックを加えるためのフレームワークです。

リクエスト送信時やレスポンス返却前に行う処理を定義できるものです。

middlewareの実装

threadlocalを操作する関数を定義

common/middlewares/threadlocals.py
from threading import local


THREAD_LOCAL = local()


def set_thread_variable(key, value):
    """ スレッドローカルデータに値を格納する
    """
    setattr(THREAD_LOCAL, key, value)


def get_thread_variable(key, default=None):
    """ スレッドローカルデータから値を取得する
    """
    return getattr(THREAD_LOCAL, key, default)


def get_request():
    """ スレッドローカルデータからリクエスト情報を取得する
    """
    return get_thread_variable('request')

middlewareクラスを定義

common/middlewares/request_store_middleware.py
from common.middlewares.threadlocals import set_thread_variable
from django.utils.deprecation import MiddlewareMixin


class RequestStoreMiddleware(MiddlewareMixin):
    def process_request(self, reuqest):
        set_thread_variable('request', reuqest)

今回はリクエストの情報がほしいのでprocess_requestのみ定義しときます。

settings.pyのMIDDLEWAREに追加

settings.py
.
..
...
MIDDLEWARE = [
    .
    ..
    ...
    'common.middlewares.request_store_middleware.RequestStoreMiddleware', # 追加
]
...
..
.

好きなところでget_requestを呼ぶだけ

僕はDBへの保存時にユーザ情報を格納するのが目的なので、models.pyで使用することにしました。

common/models.py
.
..
...
from common.middlewares.threadlocals import get_request
from django.db.models.signals import pre_save
...
..
.
class Company(BaseModel):
    """ 企業モデルクラス
    """
    ...
    ..
    .
    created_user = models.ForeignKey(User, on_delete=models.DO_NOTHING, null=True, blank=True)
    updated_user = models.ForeignKey(User, on_delete=models.DO_NOTHING, null=True, blank=True)
...
..
.
def set_user_receiver(sender, instance, *args, **kwargs)
    request = get_request() # user情報を格納する前に認証チェックをしても良いかも
    instance.created_user = request.user
    instance.updated_user = request.user


pre_save.connect(set_user_receiver, sender=Company) # pre_saveを使うと、save()実行前に呼び出したい関数を登録できる。

おわり

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1