выберите определенный атрибут во вложенном объекте в jinja

#python #jinja2 #undefined #syntactic-sugar #nested-object

#python #jinja2 #не определено #синтаксический-сахар #вложенный объект

Вопрос:

Я ищу удобный и элегантный способ отображения атрибута вложенного объекта, выбирая первый определенный.

Что-то вроде этого :

 from jinja2 import Template

o1 = { "a" : { "b" : { "c" : "John Doe" } } }
o2 = { "e" : { "f" : "John Doe" } }
o3 = { }

template = Template("""Hello {{ o.a.b.c or o.e.f or "John Doe" }}!""")

for o in [o1, o2, o3]:
    r = template.render(o=o)
    print(r)
 

Каждая печать должна выводить «Привет, Джон Доу!», первый выводит. Но затем он завершается с jinja2.exceptions.UndefinedError: 'dict object' has no attribute 'a' ошибкой.

Я пытался использовать defined , но это означало бы множественное if утверждение. Чего я бы хотел избежать.

Комментарии:

1. как насчет просто {{ o["a"] }} или {{ o.get("a","default") }}

2. согласно документации jinja o.a и o["a"] эквивалентны. И точечная нотация намного понятнее. И дело в том, что если я перепишу свой шаблон с помощью brakets, он завершится точно так же.

3. я думаю, вам нужно будет использовать o.get

Ответ №1:

кажется, это работает нормально

 >>> template = Template("""Hello {{ o.get('a',{}).get('b',{}).get('c',None) or o.get('e',{}).get('f',None) or "John Doe" }}!""")
>>> template.render(o=o2)
u'Hello John Doe!'
>>> template.render(o=o1)
u'Hello John Doe!'
>>> template.render(o=o3)
u'Hello John Doe!'
 

в противном случае, как только ключ не существует, возникает ошибка, которая приводит к короткому замыканию остальной логики … похоже на попытку индексирования в словаре с помощью несуществующего ключа

Комментарии:

1. Это, наверное, самое ясное, что я могу получить. Большое вам спасибо!

2. вы могли бы проделать хитрость с collections defaultdict, но это просто затрудняет последующую отладку, честно