Django模板中的嵌套点查找
根据《Django书籍》,Django的模板系统支持嵌套的点查找:
点查找可以嵌套多层。例如,下面这个例子使用了{{ person.name.upper }},这实际上是先查找字典中的一个键(person['name']),然后再调用一个方法(upper()):'{{ person.name.upper }} 是 {{ person.age }} 岁。'
这种方法有没有什么问题是文档中没有广泛提到的?我在使用嵌套点查找时遇到了麻烦——这是一个简单的例子:
views.py:
test = [{'foo': [1, 2, 3], 'bar': [4, 5, 6]}, {'baz': [7, 8, 9]}]
ndx = 'bar'
t = loader.get_template('meh.html')
c = Context({'test': test,
'ndx': ndx,})
return HttpResponse(t.render(c))
meh.html 模板:
<pre>
{{ test }}
{{ test.0 }}
{{ test.0.ndx }}
</pre>
生成的HTML:
<pre>
[{'foo': [1, 2, 3], 'bar': [4, 5, 6]}, {'baz': [7, 8, 9]}]
{'foo': [1, 2, 3], 'bar': [4, 5, 6]}
</pre>
在列表元素中查找字典键的嵌套查找没有返回任何结果,而我期待的是[4, 5, 6]。
J.J.
4 个回答
大卫说得对:ndx
不会被计算来获取一个键,它会被直接当作一个键来使用。你可以定义一个新的模板标签来实现你想要的功能,这里有一个简单的例子:http://www.djangosnippets.org/snippets/1412/
为了更详细地解释David的回答,Django的模板系统不允许你把上下文变量的值当作键来使用。所以,在你的例子中
{{ test.0.ndx }}
实际上是在寻找第一个项目中键为"ndx"
的值,这个项目是来自test
这个上下文变量的。
如果你需要这样的功能,就得自己实现一个模板过滤器。这个链接提供了更多信息,包括Django开发者为什么没有这个功能的原因,以及你想要的模板过滤器的示例实现。
我觉得问题在于你期待 ndx
会被计算,但实际上它根本不会被计算。你试过这样做吗:
{{ test.0.bar }}
我觉得这样做能达到你想要的效果。
这样做会有问题吗……?
有一点,但不是你想的那种问题。我觉得这不是因为嵌套的问题,或者说,在你深入一层后情况不会变得更糟。我的意思是,所有的查找参数都是字面量(就是直接的值)。这点是没法改变的。所以虽然你可以开发自定义的模板标签,并传入字面量或变量进行计算,但如果你想根据另一个值的计算结果直接访问某个变量的成员,那就真的没戏了。(你可能可以为此写一个模板标签,但它在所有情况下都不一定有效,而且可能比它值得的要复杂得多。)
不管怎么说,这看起来是这个模板语言一个相当有意图的特性。我邀请你考虑一下,访问器应该如何知道 {{ foo.bar }}
是应该被理解为 foo[bar]
还是 foo['bar']
。在不复杂化语法的情况下,似乎不可能做出有意义的判断,而这是django模板设计非常坚持要避免的事情。