2009-10-13 11 views
8

मैं जिन्जा 2 में एक बहुत ही सरल, पेड़-चलने वाला टेम्पलेट लिखने की कोशिश कर रहा हूं, कुछ कस्टम ऑब्जेक्ट्स का उपयोग ओवरलोडेड विशेष तरीकों (गेटैटर, गेटिटम इत्यादि) के साथ करता है, यह सरल लगता है, और पेड़ के बराबर पायथन चलना ठीक काम करता है, लेकिन इस बारे में कुछ है कि जिनजा का रिकर्सन काम करता है जिसे मैं समझ नहीं पा रहा हूं। कोड नीचे दिखाया गया है:Jinja2 "रिकर्सिव" टैग वास्तव में कैसे काम करता है?

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) 

टेम्पलेट एक अपवाद बढ़ा रहा है के रूप में यदि प्रत्यावर्तन वास्तव में जगह नहीं लिया। आंतरिक कॉल किया जाता है, लेकिन किसी भी तरह 'श्रेणी' का संदर्भ अभी भी माता-पिता को संदर्भित करता है। यहाँ क्या देता है? इन रिकर्सिव टेम्पलेट्स को कैसे काम करना चाहिए, इस बारे में कुछ यादगार होना चाहिए। (या कुछ मौलिक रूप से मूर्खतापूर्ण है कि मैं ऐसा कर रहा हूं कि मैं बस देख नहीं सकता।

+1

आपको पोको-लिब्स मेलिंग सूची पर पोस्ट करना चाहिए। Armin (Jinja के निर्माता) वहाँ आपकी पोस्ट देखेंगे। http://groups.google.com/group/pocoo-libs/topics –

उत्तर

7

जैसा कि मैं आपके कोड से देखता हूं, आप एक बात को छोड़कर सही ढंग से रिकर्सिव समझते हैं: यह कथन के लिए पुन: प्रयोज्य है, लेकिन ' टी अद्यतन (अपने कोड में category) अलग-अलग मूल रूप से यह में इस्तेमाल किया। इस प्रकार, बच्चों के माध्यम से आप नेस्टेड पाश दोहराता है, लेकिन मूल category में set टैग लुकअप, नहीं एक 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> 
संबंधित मुद्दे