テンプレートなどにアプリケーション名を直書きしたくないので
取得する方法がないか調べてみた話。
はじめに(やりたいこと)
Google App Engineに限らずだと思うのですが、djangoのアプリケーションを複数作成していて
以下のようにurls.py
を定義し、urlによってアプリケーションを分けているとします。
urls.py
from django.conf.urls import patterns, include, url urlpatterns = patterns('', url(r'^app_A/$', include('app_A.urls')), url(r'^app_B/$', include('app_B.urls')), url(r'^app_C/$', include('app_C.urls')), ... )
この場合、たとえば特定のアプリケーションapp_A
のテンプレートにボタンを設置しようとなると
そのactionのURLは/app_A/action
というように
/[アプリケーション名]/[実行したいアクションのURL]
となりますよね。
公式チュートリアルのguestbookでいえば、テンプレートには
index.html(抜粋)
<form action="/sign?guestbook_name={{ guestbook_name }}" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Sign Guestbook"></div> </form>
と書いてますが、このアプリケーションをhttp://localhost:8080/guestbook
以下に配置した場合、ボタンのURLは
<form action="/guestbook/sign?guestbook_name={{ guestbook_name }}" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Sign Guestbook"></div> </form>
としたいはずです。
が、このようにテンプレートに直接アプリケーション名を埋め込むのは何だか抵抗があります。
テンプレートなので、{{ app_name }}
というような形でview側から値を渡してあげたいです。
というわけで、どうやったら実現できるか調べました。
ここにあった
Stackoverflowに同じような質問をしている人が。
django - How to get the name of current app within a template? - Stack Overflow
アプリケーション名を取得する2つの方法
上のサイトに書かれていた方法としては次の2つがありました。
context processor
を使う- (django1.5以降)
request
オブジェクトのresolver_match
属性を使う
ここでは、2.の方法でやってみます。
方法
プロジェクトのurls.py
で次のようにapp_name
を指定します。
from django.conf.urls import patterns, include, url urlpatterns = patterns('', # includeメソッドの引数にapp_nameを定義する url(r'^app_A/$', include('app_A.urls', app_name='app_A')), url(r'^app_B/$', include('app_B.urls', app_name='app_B')), url(r'^app_C/$', include('app_C.urls', app_name='app_C')), ... )
include
はapp_name
の他、namespace
も指定できるようです。
(が、そっちが何に使われるのかは不明です)
(参考)https://docs.djangoproject.com/en/1.7/ref/urls/#django.conf.urls.include
そして、views.py
内でrequest.resolver_match.app_name
を取得し、テンプレート変数にセットします。
views.py
# /app_A/XXX というリクエストの時に呼ばれるメソッド def main_page(request): (中略) template_values = Context({ 'app_name': request.resolver_match.app_name, ... }) return HttpResponse(loader.get_template('index.html').render(template_values))
index.html(修正後、抜粋)
<form action="/{{ app_name }}/sign?guestbook_name={{ guestbook_name }}" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Sign Guestbook"></div> </form>
これで、アプリケーション名を直接テンプレートに書かなくても済むようになりました。
リファレンス
https://docs.djangoproject.com/en/1.5/ref/urlresolvers/#django.core.urlresolvers.ResolverMatch