在Django中,模板变量中的点理论上表示查找,基于以下分辨率顺序:
-
字典查找 . 示例:
foo["bar"]
-
属性查找 . 示例:
foo.bar
-
方法调用 . 示例:
foo.bar()
-
列表索引查找 . 示例:
foo[bar]
来自rendering a context in django 1.2(docs.djangoproject.com) .
事实上:
view :
...
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")
template :
Veggie by basket order, showing name
{% for veg in basket %}
{{ veg }}
{{ veggies.veg.name }}
{% endfor %}
output :
Veggie by basket order, showing name
a
c
b
该输出中没有素食名称 .
我认为这不是Django所说的那样 . 我很欣赏我可以写一个标签来解决这个问题 . 那很难看 .
根据Django ticket 12486,这对Django团队没有任何修复,因为"The intention is that Django's templates can be read and written by non-programmers, so complex logic should be view code or custom template tags."(Luke Plant)
我很感激在这种情况下写一些清晰的模板代码的实用建议(我有很多不同种类的“蔬菜”去引用) . 如果我们有模板编写者 - 哼 - 知道如何进行字典查找,是否值得离开Django?
3 回答
Django的模板引擎将for循环中的
veg
视为字符串,但是您尝试将其用作表达式的一部分 . 而Django 's template engine is an obstacle at times, what you are doing just doesn' t验证 . 你想要做的是获取veggies
的属性,其名称包含在对象veg
中,点符号不是't work that way either in Python or in Django'的模板 . 当你说veggies.veg时,它正在寻找名为veg
的素食者的属性,而不是名为a
,_1238383_或c
. 这不是很有意义的工作 .相反,只需将其吸取并编写模板标签以按名称访问任意对象的属性,或者将模板传递给模板中不需要这种逻辑的篮子 .
Django这样做的方法是准备用于在视图中呈现的数据结构(我认为这是为什么在django中称为“view”的“view”的原因之一),例如
然后
所以传递你想渲染的结构,而不是你得到的结构 . django认为模板编写者无法理解字典查找(或者例如一些python代码)是不正确的,django认为变量字典查找(以及任意python代码)对于模板逻辑来说过于复杂,并且有原因为了那个原因 . 我个人没有发现您的模板代码段非常易读,但这是个人喜好 .
如果您不同意这种意识形态或者它限制了您的任务,那么很容易使用模板过滤器(无论如何都无法区分dct [var]和dct ['var']和dot-syntax,以及过滤器只是一个单行,没有任何收获在django本身)或者,如果这种意识形态真的很恶心,切换到不同的模板引擎,如jinja2 .
Django阻止你快速入侵模板来解决你的问题,因为它强制模板作者和视图作者之间的分离 . 想象一下,您销售了10,000种不同的蔬菜,并将它们保存在数据库表中 . 您是否真的想将所有10,000种蔬菜的字典传递到模板中以实现您所描述的内容?
如果您使用真实模型而不是类和字典构建此示例,您可能已经拥有了所需的内容:"basket"将是一个具有"veggie"的外键引用的对象,以便
basket_item.veggie
将引用Veggie表中的行(呃,没有双关语意 . 您可以简单地传入篮子,当从模板引用时,素食项目将根据需要填充 . 为了提高效率,在获取篮子项目时,最终可能会使用.select_related
来预先填充单个SQL查询中的素食项目 .