[Django] すべてのテンプレートで共通の変数を扱う方法3パターン

Djangoで開発しているとすべてのページで同じ変数を利用したい場合って出てきますよね。

そんな時に覚えておくと楽に記述ができるかもしれない方法です。

愚直に書く

愚直にすべての関数ビュー、クラスビューに同じように変数を記述します。

こんなものは紹介するまでもなく、誰でも思いつきそうなものですが…

継承を利用する

クラスビューを利用する場合に、共通の変数を扱うクラスを作って継承させる方法です。

class CommonTemplateView(TemplateView):
    """すべてのテンプレートで利用する変数を定義したクラス"""
    def get_context_data(self, **kw):
        context = super().get_context_data(**kw)
        context.update({"context1": "value"})
        return context

このようなクラスを作った後、他のクラスビューに継承させる。

class IndexView(CommonTemplateView): # 先ほど定義した共通の変数を持つクラスを継承
    template_name = "application/index.html"

    def get_context_data(self, **kw):
        context = super().get_context_data(**kw)
        context.update({"title": "index"})
        return context

コンテキストプロセッサーを利用する

こちらが最もスマートな記述だと思います。

まずは共通の変数を管理する用のファイルを準備しましょう。

django_project
├── application
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── templates
│   │   └── application
│   │       └── index.html
│   ├── tests.py
│   ├── urls.py
│   ├── utils.py
│   └── views.py
├── manage.py
└── django_project
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

こんな感じのプロジェクト構成だとしましょう。
そこにdjango_project/application/my_context_processor.pyを作ります。

中身はこんな感じにしておきます。

def common(request):
  return {"context1": "value"}

引数を一つ受け取る関数なら、関数の名前は何でも構いません。

受け取る引数は、関数ビューの第一引数で受け取るのと同じWSGIRequestオブジェクトです。

戻り値は辞書にします。

この辞書の中身がすべてのテンプレートで使える変数になります。

次にsettings.pyTEMPLATESの中身を確認します。

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

たぶん上記のようになっていると思います。

この'context_processors'のリスト部分に先ほど作ったmy_context_processor.pycommon関数を登録します。

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'application.my_context_processor.common' # 追記
            ],
        },
    },
]

これですべてのテンプレートで変数context1が使えるようになりました。

最後に

三つ紹介するとか書いてましたが、実質二つでした、ごめんなさい…
基本的にはコンテキストプロセッサーを利用する方法が、もっとも簡単にできますし、構成がすっきりするのがおすすめです。