在Django中,模板变量中的点理论上表示查找,基于以下分辨率顺序:
foo["bar"]
foo.bar
foo.bar()
foo[bar]
来自rendering a context in django 1.2(docs.djangoproject.com)。
实际上:
查看:
...
class Veggie(object):
def __init__(self, name):
self.name = name
veggies = {'a': Veggie('carrot'), 'b': Veggie('lettuce')}
basket = ['a', 'c', 'b']
return render_to_response('tpls/veggies.txt',
{'veggies': veggies, 'basket': basket},
mimetype="text/plain")
模板:
Veggie by basket order, showing name
{% for veg in basket %}
{{ veg }}
{{ veggies.veg.name }}
{% endfor %}
输出:
Veggie by basket order, showing name
a
c
b
该输出中没有素食名称。
我认为这不是Django所说的。我很欣赏我可以用la Peter Harkins "Django Template Tag for Dictionary Access"编写标签来解决问题。那很难看。
根据Django ticket 12486,这是Django团队的 no fix 因为“意图是Django的模板可以由非程序员读取和编写,所以复杂的逻辑应该是查看代码或自定义模板标签。“ (卢克工厂)
我很感激在这种情况下编写清晰的模板代码的一些实用建议(我有很多不同种类的“蔬菜”可以解除引用)。如果我们有模板编写者 - 哼 - 知道如何进行字典查找,是否值得离开Django?
答案 0 :(得分:2)
Django的模板引擎将for循环中的veg
视为字符串,但您尝试将其用作表达式的一部分。虽然Django的模板引擎有时是一个障碍,但你所做的只是没有验证。你想要做的是获取veggies
的属性,其名称包含在对象veg
中,并且点符号在Python或Django的模板中不起作用。当您说veggies.veg时,它正在寻找名为veg
的蔬菜的属性,而不是a
,b
或c
。这不是Django模板引擎的缺陷;这就是Python(以及我所知道的每种语言)的工作方式。
相反,只需将其填充并编写模板标记以按名称访问任意对象的属性,或者将模板传递给模板中不需要该类逻辑的篮子。
答案 1 :(得分:1)
Django这样做的方法是准备在视图中渲染的数据结构(我认为这是django中称为“视图”的“视图”的原因之一),例如。
basket = [veggies[veg_id] for veg_id in basket_id_list]
然后
{% for veg in basket %}
{{ veg.name }}
{% endfor %}
所以传递你想要渲染的结构,而不是你得到的结构。 django认为模板编写者无法理解字典查找(或者例如一些python代码)是不正确的,django认为变量字典查找(以及任意python代码)对于模板逻辑来说过于复杂,并且有理由为了那个原因。我个人没有发现您的模板代码段非常易读,但这是个人喜好。
如果您不同意这种意识形态或者它限制了您的任务,那么很容易使用模板过滤器(无论如何,无法用点语法区分dct [var]和dct ['var'],并且过滤器只是一个单行,在django本身没有任何好处)或者,如果这种意识形态真的很恶心,请切换到不同的模板引擎,如jinja2。
答案 2 :(得分:0)
Django阻止您在模板中快速入侵以解决您的问题,因为它强制模板作者和视图作者之间的分离。想象一下,您销售了10,000种不同的蔬菜,并将它们保存在数据库表中。您是否真的想将所有10,000种蔬菜的字典传递到模板中以实现您描述的内容?
如果您使用真实模型而不是类和字典构建此示例,您可能已经拥有了所需内容:“篮子”将是一个对象,其外键引用“素食”,以便{{1}会引用Veggie表中的一行(呃,没有双关语)。您可以简单地传入篮子,当从模板引用时,素食项目将根据需要填充。为了提高效率,您最终可能会在获取购物篮项目时使用basket_item.veggie
来预先填充单个SQL查询中的素食项目。