tags:

views:

24

answers:

2

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)

+1  A: 

I would define a boolean and a macro and go from there. Instead of printing the variable, you print the result of the macro which uses an if statement and the boolean to decide if it should print. So, you get the following:

{{ 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) %}
nearlymonolith
+2  A: 

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.

LeafStorm