naritoブログ

【お知らせ】
新ブログができました。今後そちらで更新し、このサイトは更新されません(ウェブサイト自体は残しておきます)
このブログの内容に関してコメントしたい場合は、新ブログのフリースペースに書き込んでください

このブログの内容を新ブログに移行中です。このブログで見つからない記事は、新ブログにありま

Djangoで、requestオブジェクトをグローバル変数として扱う

約319日前 2017年12月30日0:02
プログラミング関連
Django Python
Djangoのビューにはリクエストオブジェクトが渡されます。しかし、ビューにしか渡されないので、受け渡しはビューを介して行う必要があります。(一応、テンプレートにも暗黙のうちに渡されます)
ビューから渡せるのであればまだいいのですが、それだと厳しいケースがあります。
例えば、テンプレートフィルタ内でリクエストオブジェクトを触りたい場合はどうでしょうか。テンプレートタグと違い、引数を渡すことはできません...

そこで、そもそもrequestをグローバルな変数として利用できるようにするのが今回の目的です。
このような方法はあまり推奨されませんが、念の為覚えておくとちょっとお得です。

プロジェクト名を「project」
アプリケーション名を「app」
とします。

まず、ミドルウェアを作成します。ミドルウェアの段階で、requestオブジェクトをどこかに保存するのです。
app内に、middleware.pyを作成し、以下のような中身にします。

from threading import local

_global = local()


def global_request(get_response):
def middleware(request):
_global.request = request
response = get_response(request)
return response
return 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',
'app.middleware.global_request', # 追加!
]



後は、使いたい場所からアクセスするだけです。
試しに、テンプレートフィルタからrequestにアクセスするならば以下のようになります。

from django import template
from app.middleware import _global # このimportが必要

register = template.Library()


@register.filter
def test(value):
request = _global.request # ここでrequestを取得
# requestを使った処理...
# ...

return value




middlewareモジュールの_global属性のimportをし、request属性を使うだけです。

from app.middleware import _global
...
...
request = _global.request



middleware.pyの解説をしましょう。
threading.local()ですが、これは各スレッド毎に固有の値を管理することができます。この各スレッドは各ユーザーに対応しており、他のユーザーのrequestを誤って使うことはまずありません。(Webサーバー側の実装にもよるかも)
Djangoにはタイムゾーンがありますが、各ユーザーのタイムゾーン情報もthreading.local()を使って管理しています。(django.utils.timezone.py)

from threading import local

_global = local()



ミドルウェアを作成するには、クラスを定義するか関数を定義するかの2つがあります。今回はシンプルな関数を使い、_globalのrequest属性にrequestを保存しておきました。

def global_request(get_response):
def middleware(request):
_global.request = request
response = get_response(request)
return response
return middleware