Template tagでrequest.pathがActiveページか判別する

Blogなどで、メニュー/ナビなどlistタグを使って表示します。
htmlファイルで作ったサイトであれば簡単に表現できますが、
Djangoでは、テンプレートのみでは表現できません。

そこでTemplate tagを使って実現させましょう。

メニュー/ナビの仕様

  1. listタグで作成。
  2. カレントページには、classに"active"をつける
  3. メニュー/ナビは Home(/), Blog(/blog/), About(/about/)とします。
    home, aboutはFlatpagesで作成しています。
  4. listタグで構成されたメニュー/ナビは、base.html内にあるものとします。

settings.pyの編集

"django.core.context_processors.request"を使うため、settings.pyの"TEMPLATE_CONTEXT_PROCESSORS"に追加します。

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.request', #追加
)

Blog表示のviews.py

views.py

from django.template import RequestContext
from django.shortcuts import render_to_response
…
def blog(request):
    …
    return render_to_response('blog/page.html', {…}, 
                    context_instance = RequestContext(request))

Template tag作成

activeタグを作成します。

tags.py

from django import template

register = template.Library()

@register.simple_tag
def active(request, pattern):
    if request.path.startswith(pattern):
        return "active"

    return ""

テンプレートの作成

base.html(抜粋)

…
{% load tags %}
…
<ul>
<li><a class = {% active request "/" %}" href = "/">Home</a></li>
<li><a class = {% active request "/blog/" %}" href = "/blog/">Blog</a></li>
<li><a class = {% active request "/about/" %}" href = "/about/">About</a></li>
</ul>
…

検証

各ページにアクセスしてhtmlのソースを確認してみてください。
Blog, AboutにアクセスしたときHomeも"active"になってしまいます。
一見実現しているようですが、あともう一歩です。

Template tagとテンプレートの修正

"active"の判断はstartswithではなく、reモジュールを使います。
patternはurls.pyのように正規表現を使います。

tags .py

from django import template

register = template.Library()

@register simple_tag
def active(request, pattern):
    import re
    if re.search(pattern, request.path):
        return 'active'

    return ''

base.html

…
{% load tags %}
…
<ul>
<li><a class = {% active request "^/$" %}" href = "/">Home</a></li>
<li><a class = {% active request "^/blog/" %}" href = "/blog/">Blog</a></li>
<li><a class = {% active request "^/about/" %}" href = "/about/">About</a></li>
</ul>
…

これでrequest.pathごとに"active"をつけることができました。
あとはCSSを編集してデザインにあわせます。

twitter 2009-04-13 21:27:44.953770

参照サイト

Recent Updates

URLConf Tip 01 - キャプチャの有無にかかわらず同一のviewで処理する
Markdownの入力補助"wmd"をAdmin siteで使う
ModelFormでfieldのwidgetを変更する
動的なformを作る 6 - Dynamic Inline Admin site編
Formsetsを使う3 - inlineformset_factory編
動的なformを作る 5 - django-dynamic-formset編
Formクラスからメディアを定義する
複数のmodelを結合する 2 - Proxy model編
複数のmodelを結合する 1
ModelFormでfieldの表示順番を変える
Admin siteのwidgetを個別に変更する
formfield_overridesを使ってAdmin siteのwidgetを変更する
Admin siteのlist_displayをカスタマイズする - リンク編
Admin siteのlist_displayをカスタマイズする - 基本編
Admin siteのTextareaの高さを自在に変更する - admin.py編