2009-10-13 15 views
8

Ben jinja2, çok özel, özel yöntemler (getattr, getitem, vb) bazı özel nesneler kullanarak, çok basit, ağaç-basılı bir şablon yazmaya çalışıyorum Basit görünüyor ve ağacın eşdeğer python yürümek iyi çalışıyor, ama Jinja'nın özyinelemesinin anlamadığım yolla ilgili bir şey var. kod aşağıda gösterilmiştir: özyineleme aslında yer almadı sankiJinja2 "özyinelemeli" etiketi aslında nasıl çalışıyor?

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) 

şablon istisna yükseltiyor. İç arama yapılır, ancak bir şekilde 'kategori' referansı hala ebeveyne başvurur. Burada ne veriyor? Bu özyinelemeli şablonların nasıl çalışması gerektiğine dair çok temel bir şey olmalı. (Ya da çok temelden aptalca bir şey yapıyorum ki bunu göremiyorum.

+1

pocoo-libs posta listesine yazmalısınız. Armin (Jinja’nın yaratıcısı) yayınınızı burada görecek. http://groups.google.com/group/pocoo-libs/topics –

cevap

7

Kodunuzdan görüldüğü gibi, tek bir şey hariç, özyinelemeyi doğru anlıyorsunuz: bu, for ifadesinde yinelenen yerine geçiyor, ancak ' başlangıçta içinde kullanılan t güncelleme (kodunuzda category) değişkeni. Böylece orijinal category içinde iç içe geçmiş çocuklarda aracılığıyla döngü yinelenir ancak set etiket aramaları, bir değil loop() geçti.

Ben self.items.iteritems() dönmek için __iter__() yöntemini değiştirmeyi önermek ve şablon için: