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()実行前に呼び出したい関数を登録できる。
おわり