Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make sure a Jinja custom tag only outputs once?

Tags:

python

jinja2

I have a custom tag in Jinja2 that I want to output something only the first time that it is called. So say I have the following template:

1. {% only_once %}
2. {% only_once %}
3. {% only_once %}

I want the output to be:

1. "I only get printed once!"
2.
3.

I'm guessing the best way to do this is to set a flag in the context of the template to track whether I've already printed something or not. Here's a code sample, but is this right?

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

Is that correct? I read some stuff about the context is immutable, so will this not work? (see http://jinja.pocoo.org/2/documentation/api and search for immutable)

like image 441
Bialecki Avatar asked Dec 03 '22 05:12

Bialecki


2 Answers

If you want to do it purely with Jinja you can just check the loop.index variable in that fashion,

{% for bar in bars %}
    {% if loop.index == 1 %}
        Print me once
    {% endif %}
    Print me every time
{% endfor %}
like image 189
topless Avatar answered Jan 06 '23 01:01

topless


My suggestion is to implement this in Python code:

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 ''

Create an OnlyOnce instance in your Python code and pass it to the template, and then every time you want to use it, just use {{ only_once }}.

One thing I notice about a lot of people using Jinja is that they want to do things in a Django-ish way, that is, writing extensions. But Jinja's expressions/importing/whatever is powerful enough that you don't have to use extensions for everything.

And yes, using the context.my_flag thing is a bad idea. Only the template gets to modify the context. EVER.

like image 24
LeafStorm Avatar answered Jan 06 '23 01:01

LeafStorm