AWS / PHP / Python ちょいメモ

amazon web service , PHP, Python を使ったときのメモ。日本語でググってもわからなかった事を中心に。

Djangoアプリ全体で使う変数をコンテキストプロセッサで提供

組み込み Template とかをみてると {{ MEDIA }} とかが出てきますが、これを自前で作る方法。同じアプリを複数サイトで立ち上げる必要が出てきて、区別の為、アプリごとにユニークな名前を表示したい。ただ、それだけの用途に使いました。

Django 1.7 の admin のように基底クラスの中で変数を定義して継承、もしくはCookieに値をセット、なども気づいたのですが、今回は修正が少なくて済む context processor を用意する方法を選択)


環境:

  • python 2.7.6
  • Django 1.6.11 (1.8から?は仕様が変更になってるようなので、後日確認)

Template と Context

Template 上で扱いたいオブジェクトや値は、Viewからcontextに入れて渡すというのが通常の流れ。

view.py

class IndexView(TemplateView):
    template_name = 'index.html'
...
    context['application_name'] = 'HogeHoge'

app/templates/index.html

<h1>{{ application_name }}</h1>

しかし、全Viewに対してアプリ名を渡すとなると、各Viewのcontextにアプリ名を渡していく修正が発生するので手間がかかる。

Context Processor で Context に値を追加

そこで、新しく必要な値を渡す コンテキスト プロセッサを作り、context を生成する度に、特定の変数を渡せるようにします( {{ MEDIA }} のような)。

今回は、アプリ名を渡したいだけなので、settings.py に新しい変数を定義して、それを参照するという事をやります(settings.py中の変数名は、大文字を使おうという記述があったと思うので、それにならって記載)。

app/settings.py :

from django.conf import global_settings
TEMPLATE_CONTEXT_PROCESSORS = \
    global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
    'app.context_processors.app_name',
    )

APP_NAME = 'My App'

Django1.6 の場合 : TEMPLATE_CONTEXT_PROCESSORS は、デフォルト値も記載がなかったので、グローバルで定義されている値に追加してます。リスト形式なのでカンマを忘れずに。

app/context_processors.py

from django.conf import settings
def media(request):
    return {'APP_NAME': settings.APP_NAME}

上記の設定が終われば、Viewで処理しているテンプレートで次の記述を行うことで、変数を参照できるようになります。View毎にcontextに変数を渡す必要はありません。

app/templates/index.html

<h1>{{ APP_NAME }}</h1>

感想

context processor という名前から、仰々しく思ってしまったのですが、手を入れてしまえば簡単。内部まで、動作がはっきり見えるのは、オープンソースの気持ちいいところだなぁと感じました。

この解法がベストか?という点は、持ちネタが少ないため分からないというのが正直な所です。(ASPでいうところの、アプリケーション変数みたいな起動中に自由に参照できる変数みたいな、ライトなイメージの機能はあったりしないのでしょうかね?F/W違うので、無茶とは思いつつも)

# もっと良い方法があれば、教えてください〜

参考サイト

その他

Django 1.8 では、context processors の定義が core から template に移っているとのことです。

Changed in Django 1.8:
Built-in template context processors were moved from django.core.context_processors to django.template.context_processors in Django 1.8.