سؤال

أحاول أن أكتب قالبًا بسيطًا جدًا للمشي في 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>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top