Как убедиться, что индивидуальный тег Jinja только один раз выводит?
Вопрос
У меня есть пользовательский тег в Jinja2, который я хочу выводить что-то только в первый раз, когда он называется. Так сказать, у меня есть следующий шаблон:
1. {% only_once %}
2. {% only_once %}
3. {% only_once %}
Я хочу, чтобы вывод был:
1. "I only get printed once!"
2.
3.
Я предполагаю, что лучший способ сделать это - установить флаг в контексте шаблона для отслеживания того, уже напечатал что-то или нет. Вот образец кода, но это правильно?
class OnlyOnceExtension(Extension):
tags = set(['only_once'])
@contextfunction
def parse(self, context, parser):
if hasattr(context, 'my_flag') and context.my_flag:
return Output("")
else:
return Output("I only get printed once!")
Это правильно? Я прочитал некоторые вещи о контексте неизменно, так будет ли это не работать? (видеть http://jinja.pocoo.org/2/documentation/api. и поиск неизменных)
Решение
Мое предложение заключается в том, чтобы реализовать это в коде Python:
class OnlyOnce(object):
def __init__(self, data):
self.data = data
self.printed = False
def __str__(self):
if self.printed is False:
self.printed = True
return self.data
return ''
Создать OnlyOnce
экземпляр в вашем коде Python и передайте его на шаблон, а затем каждый раз, когда вы хотите использовать его, просто используйте {{ only_once }}
.
Одна вещь, которую я заметил о многих людях, использующих Jinja, - это то, что они хотят делать вещи в виде Джанго-острого, то есть написание расширений. Но выражения / импортирование детей Jinja / что бы ни было достаточно мощным, что вам не нужно использовать расширения для всего.
И да, используя context.my_flag
вещь плохая идея. Только шаблон получает изменение контекста. КОГДА-ЛИБО.
Другие советы
Если вы хотите сделать это чисто с Jinja, вы можете просто проверить переменную Loop.index таким образом,
{% for bar in bars %}
{% if loop.index == 1 %}
Print me once
{% endif %}
Print me every time
{% endfor %}
Я бы определил булевую и макрос и уходил оттуда. Вместо печатать переменную, вы печатаете результат макроса, который использует оператор IF и Boolean, чтобы решить, должен ли оно печатать. Итак, вы получаете следующее:
{{ set was_printed = false }}
{% macro print_once(to_print) %}
{% if was_printed is sameas false %}
{{ to_print }}
{% set was_printed = true %}
{% endif %}
{% endmacro %}
1. {% print_once(only_once) %}
2. {% print_once(only_once) %}
3. {% print_once(only_once) %}