どのようにJinja2の「再帰」のタグが実際に作業をしますか?
質問
私はオーバーロードされた特別な方法でいくつかのカスタムオブジェクトを使用して、Jinja2の中に非常に単純な、木歩行テンプレートを記述しようとしている(GETATTR、GetItem関数など)、それは簡単なようで、木の同等のpython徒歩罰金に動作しますしかし、神社の再帰が、私は理解していないことを動作する方法についての何かがあります。コードを以下に示す:
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
に渡された1における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