如何在Jinja2的“递归”标签的实际工作?
题
我试图写在Jinja2的一个非常简单的,树遍历模板,使用具有重载特殊方法(GETATTR,的GetItem等),这看起来非常简单一些自定义对象,而树的蟒蛇相当于步行做工精细,但有一些事神社的递归工作,我不明白的方式。的代码如下所示:
from jinja2 import Template
class Category(object):
def __init__(self, name):
self.name = name
self.items = {}
self.children = True
def __iter__(self):
return iter(self.items)
def add(self, key, item):
self.items[key] = item
return item
def __getitem__(self, item):
return self.items[item]
def __getattr__(self, attr):
try:
return self.items[attr]
except KeyError:
raise AttributeError(attr)
def __str__(self):
return "<Category '%s'>" % self.name
template = '''
<saved_data>
{% for key in category recursive %}
{% set item = category[key] %}
{% if item.children %}
<category name="{{key}}">
{{ loop(item) }}
</category>
{% else %}
<item name="{{ key }}" value="{{ item }}" />
{% endif %}
{% endfor %}
</saved_data>
'''
b = Category('root')
c = b.add("numbers", Category('numbers'))
c.add("one", 1)
c.add("two", 2)
c.add("three", 3)
d = b.add("letters", Category('letters'))
d.add('ay','a')
d.add('bee','b')
d.add('cee','c')
e = d.add("bools", Category('bools'))
e.add('tru', True)
e.add('fals', False)
def walk(c, depth=0):
for key in c:
item = c[key]
print (' '*depth) + str(item)
if hasattr(item, 'children'):
walk(item, depth+3)
print "Python walking the tree:"
walk(b)
print ""
print "Jinja2 Walking the tree:"
t = Template(template)
print t.render(category = b)
在模板抛出一个异常,仿佛递归实际上并没有发生。内调用时,但不知何故提及“类别”仍然指父。这里是什么让?必须有一些非常基本的,我缺少有关这些递归模板是如何工作的。 (或者一些非常愚蠢的根本,我做,我只是看不到。
解决方案
当我从你的代码中看到你理解递归正确,除了一两件事:它代替迭代中的语句,但不更新变量(在你的代码category
)最初在其使用。因此,你在原来的set
,不是一个传递给category
嵌套通过孩子循环迭代,但loop()
标签查找。
我建议改变__iter__()
方法返回self.items.iteritems()
和模板:
<saved_data>
{% for key, item in category recursive %}
{% if item.children %}
<category name="{{key}}">
{{ loop(item) }}
</category>
{% else %}
<item name="{{ key }}" value="{{ item }}" />
{% endif %}
{% endfor %}
</saved_data>
不隶属于 StackOverflow