Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何确保Jinja自定义标记只输出一次?_Python_Jinja2 - Fatal编程技术网

Python 如何确保Jinja自定义标记只输出一次?

Python 如何确保Jinja自定义标记只输出一次?,python,jinja2,Python,Jinja2,我在Jinja2中有一个自定义标记,我只想在第一次调用它时输出它。假设我有以下模板: 1. {% only_once %} 2. {% only_once %} 3. {% only_once %} 我希望输出为: 1. "I only get printed once!" 2. 3. 我猜最好的方法是在模板的上下文中设置一个标志来跟踪我是否已经打印了一些东西。这是一个代码示例,但这是对的吗 class OnlyOnceExtension(Extension): tags = set

我在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!")

对吗?我读到一些关于上下文是不可变的东西,所以这不起作用吗?(请参阅并搜索不可变)

我将定义一个布尔值和一个宏,然后从那里开始。不打印变量,而是打印宏的结果,该宏使用if语句和布尔值决定是否打印。因此,您可以得到以下结果:

{{ 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) %}

我的建议是在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 ''
在Python代码中创建一个
OnlyOnce
实例并将其传递给模板,然后每次需要使用它时,只需使用
{{only_once}

我注意到很多使用Jinja的人都想用类似Django的方式做事,也就是说,编写扩展。但是Jinja的表达式/导入/任何功能都非常强大,您不必对所有内容都使用扩展


是的,使用
上下文。我的标志
是个坏主意。只有模板可以修改上下文永远。

如果您想纯粹使用Jinja,只需以这种方式检查loop.index变量

{% for bar in bars %}
    {% if loop.index == 1 %}
        Print me once
    {% endif %}
    Print me every time
{% endfor %}

Jinja并不总是重新计算宏,因此设置宏变量不会阻止值被创建两次。接受的解决方案可以工作,但它要求您在flask视图级别硬编码对象。 我通过创建一个定制的jinja过滤器来解决这个问题,该过滤器在每个请求中只返回一次值

过滤器:

将过滤器添加到烧瓶应用程序中

创建一个包含您只想输出一次的文本的jinja宏: macros.html

{% macro my_macro() %}
This text should only be created once
{% endmacro %}
以及如何使用它:


我试图使用此宏,但其无效代码,
TemplateSyntaxError:expected token'end of print statement',get'was_printed'
第一行必须是
{%set was_printed=false%}
。您的解决方案更有意义。我曾经遇到过类似的问题,但现在问题解决了。多亏了你,伙计。我希望我能把这个答案变成一个关于StackOverflow的新问题,因为noobs,loli必须对这个问题多留一点评论……无论谁理解这个答案,首先都有能力克服这个问题。这对社区有什么帮助?看起来这个答案对程序员来说是一个更高的思考维度。我们必须假定读者完全理解面向对象编程的四个原则吗?如果我们不做这个假设,你用什么原则来优化最初的尝试?
app.jinja_env.filters['onetime'] = onetime
{% macro my_macro() %}
This text should only be created once
{% endmacro %}
{{ my_macro() | onetime('a_name') }}
{{ my_macro() | onetime('a_name') }}
{{ my_macro() | onetime('a_name') }}