2009-12-12 73 views
20

我有这种风格的模板Django的:传递参数父模板

project 
- main_templates (including nav bar) 
-- app1 
--- app1_base_template 
--- app1_templates 
-- app2 
--- app2_base_template 
--- app2_templates 

所以渲染时,app2_templates延伸app2_base_template延伸main_template。

我需要做的是在app2的模板被渲染时显示相应的导航项目(用于显示用户在哪里)。

如果我可以在{%block xxx%}部分中传递一个变量,那么最容易。 这可能吗?

还有什么其他的通用方法?

+0

你检查了吗? http://stackoverflow.com/questions/1024168/django-is-there-a-better-way-to-bold-the-current-page-link – rinti

+2

该CSS解决方案看起来很难维护,并需要添加信息在3个不同的地方。 – Boris

回答

41

您是否尝试了{%with%}模板标记?

{% block content %} 
    {% with 'myvar' as expectedVarName %} 
    {{block.super}} 
    {% endwith %} 
{% endblock content %} 
+0

对不起,不要这样做。这是在base.html,是'block.super'旨在引用navbar ...?我的导航栏中包含了我的导航栏,*然后是我的“块内容”...应该如何设置此功能? – Pureferret

+3

有趣的黑客,但不是一个完整的解决方案。父模板需要大部分都被'{%block content%}'包围,这样才能工作,并且这可以防止我在'content'内覆盖另一个块。 – Kos

+0

在Django 1.11+中更改了语法,即使仍然支持旧语法:https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#with。{%with'myvar'as expectedVarName% } => {%with expectedVarName ='myvar'%} – ThePhi

2

来自父模板的变量会自动包含在子范围中。你的标题说你想传递一个变量给父母,这是没有道理的,因为你不能在模板中定义变量。如果你需要父变量和子变量,只需在视图中声明它。

8

没有直接的方法来按照您描述的方式向模板继承树传递变量。人们实现导航栏的方式突出显示当前页面,这通常会根据网站本身的性质进行调整。这就是说,我已经看到了两种常用的方法:

技术含量低的方法

中,表示该选项卡已激活模板的上下文传递一个变量:

# in views.py 
def my_view(request): 
    return render_to_response('app2_template.html', {"active_tab": "bar"}, 

<!-- Parent template --> 
<div id="navigation"> 
    <a href="/foo" {% ifequal active_tab "foo" %}class="active"{% endifequal %}>Foo</a> 
    <a href="/bar" {% ifequal active_tab "bar" %}class="active"{% endifequal %}>Bar</a> 
</div> 

越高技术方法

实施custom template tag呈现您的导航栏。让标签采用一个变量,指示哪一部分是活动的:

<!-- Parent template --> 

<div id="navigation">{% block mainnav %}{% endblock %}</div> 

<!-- any child template --> 
{% load my_custom_nav_tag %} 
{% block mainnav %}{% my_custom_nav_tag "tab_that_is_active" %}{% endblock %} 

您可以从那里疯狂地发疯。您可能会发现某人已经在djangosnippets.org上实施了一些适合您的功能。

+0

+1为高科技方法。带我进行了一些研究,以使其能够奏效,提供一些详细说明和参考资料,说明将来哪些文件可以帮助某些人。 – SpiRail

1

可悲的是我找不到一个干净的方式。

最后决定将标签中的每个应用的base.html文件:(。其实我用两个一组由应用程序的基本主导航一个由应用页面的应用程序的导航栏设置)

<span class="main_nav_bar_hint" id="2"></span> 

,并在项目有点JQuery的魔法base.html文件

$(document).ready(function() { $("#nav_menu_" + $(".main_nav_bar_hint").attr("id")).removeClass("normal").addClass("selected"); }) 

它是一个黑客攻击的一位,但这样一来它很容易理解,我只需要做出合乎逻辑的变化,一旦加入更多的应用程序。

2

无法在模板包含中传递参数是Django模板系统的许多缺陷之一。

我不得不处理几乎相同的问题:深层嵌套的模板需要使父模板以不同的方式进行格式化/高亮显示。

可能的解决方案:

  1. 使用“超级语境”程序,其基于在地方层级你是在一个数量的值。即super_context = MySuperContext(request,other,values等),其中super_context是一个字典,您传递给视图(或RequestContext)。这是最常用的Django-thionic(?)方法,但这意味着表示逻辑已被推回到视图中,这对我来说是错误的。

  2. 使用expr模板标签在较低级别的模板中设置值。注意:这仅适用于{%include%}模板,因为它必须在包含发生之前进行评估。你不能用{%extends%}来做到这一点,因为这必须是子模板中的第一件事。

  3. 切换到Jinja2模板,至少对于您需要这样做的意见。

一旦你有这些值设定,你可以做这样的事情:

<div class="foo{% if foo_active%}_active{%endif%}"> stuff </div> 

这使得DIV类“富”时,它不是主动和“foo_active”当它。风格品尝,但不要添加太多肉桂。 :-)

2

我已贾勒特哈迪的“低技术”的做法类似的,呃...上下文(是的,这是一个双关语......这不会使绝对意义上你,除非我告诉你,我没有做导航,但设置了按钮的边框颜色以显示哪个按钮被按下)。

但我认为我的版本更紧凑。我不是只在视图中定义一个简单的上下文变量activebar,而是返回一个字典,但始终只有一个键值对:例如activebar = {'foo':'active'}。

然后在模板中,我简单地在foo锚点中写入class =“{{activebar.foo}}”,并相应地在其他锚点中写入class =“{{activebar.foo}}”。如果只有activebar.foo被定义为具有“active”值,那么bar锚点中的activebar.bar将不会执行任何操作。也许“默默地失败”是恰当的Django谈话。鲍勃是你的叔叔。

编辑︰哎呀......一两天过去了,虽然我上面写的东西确实为我工作的问题出现了,当我把一个新的窗口作为目标放入导航栏的锚点。这似乎是一个奇怪的故障的原因:在点击新窗口(Firefox中的选项卡),然后返回到启动新窗口的那个窗口后,当我快速移动窗口时,导航栏下面的部分显示为空白光标在导航栏上的项目---没有点击任何东西。我不得不通过移动滚动条来强制屏幕重绘(不是页面重新加载,尽管这也起作用,因为它涉及屏幕重绘)。

我太过分了,不知道为什么可能会发生。而且有可能我做了一些其他的事情,导致不知怎么的事情消失了。但是...我发现了一个更简单的方法,对我来说非常合适。我的情况是,从视图中启动的每个子模板都应该使关联的导航栏项目显示为“活动”。事实上,那个navbar项目是启动了启动子模板的视图 - 通常的交易。

我的解决方案---让我们以“登录”导航栏项为例---将其放入包含登录窗体的子模板中。

{% block login %}active{% endblock %} 

我把它放在标题栏下面,但我不认为这个位置是重要的。然后,在包含导航栏定义,围绕在登录导航栏项目,我把锚...好LI标记,这里的父模板的代码:

<li class="{% block login %}{% endblock %}"><a href="/mysite/login">Login</a></li> 

因此,当子模板被渲染的父母会将登录导航栏项目显示为活动状态,而Bob仍然是您的叔叔。

我上面描述的字典方法是显示哪一行按钮被按下,当它们都在同一个子模板上​​时。这仍然适用于我,因为只涉及一个儿童模板,我不明白我的新的navbars方法在这种情况下会如何工作。请注意,使用navbars视图的新方法甚至不涉及。简单!