我正在重新设计一个Django站点,它被分成几个部分。每个部分都有一组单独的导航。我在纠结如何最好地突出正确的那个。
最初,我开始在视图中设置上下文变量,并使用它来选择正确的子导航。如:
# views.py
class HomeView(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context = super(HomeView, self).get_context_data(**kwargs)
context['subnav'] = 'news'
return context
# templates/base.html
{% if subnav %}
<ul>
{% if subnav == 'news' %}
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
{% elif subnav == 'sport' %}
<!-- etc -->
{% endif %}
</ul>
{% endif %}
那很好…但前提是每个页面都有视图。例如,所有的flatpage都没有。
我在上下文处理器和模板标签上转了一圈又一圈,似乎没有什么令人满意的。什么好主意吗?
(一种明显的方法是将每个子导航HTML放在单独的模板中,并从这些模板扩展到单独的页面…但是我已经在不同类型的布局中使用了模板继承,并且添加section的维度会使事情变得非常复杂。我已经想出了一个看似合理的解决方案。
我做了一个自定义的赋值标签,它为当前页面设置子导航的名称:
# templatetags/nav_tags.py
from django import template
register = template.Library()
@register.assignment_tag
def get_subnav(request):
# The names on the right are the names of URLs:
subnavs = (
('news', ('home', 'news_archive', 'news_month_archive')),
('sport', ('sport_home', 'sport_archive', 'sport_month_archive')),
# etc
)
url_name = request.resolver_match.url_name
for subnav, names in subnavs:
if url_name in names:
return subnav
return False
指出:
- 这假设你在
urls.py
中使用命名url。 -
request.resolver_match.url_name
仅在Django 1.5之后可用。
然后在模板中我可以做:
{% load nav_tags %}
{% get_subnav request as subnav %}
{% if subnav %}
<ul>
{% if subnav == 'news' %}
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
{% elif subnav == 'sport' %}
<!-- etc -->
{% endif %}
</ul>
{% endif %}
这样做的好处是减少了"if"请求的数量。路径=这个或请求。Path =那个或者request.path=…"不依赖于任何地方的实际URL路径的好处,这对我来说总是很脆弱——这就是命名URL的作用。
我还制作了一个上下文处理器,将url_name
放在模板上下文中,因为我发现它对周围有用,并阻止我依赖于其他地方的URL路径。