Home > Enterprise >  Calling a jinja2 filter with only the context as an argument
Calling a jinja2 filter with only the context as an argument

Time:03-08

I'm trying to render a jinja2 template in my service (not using flask, just pure jinja2 and constructing a jinja2 Environment.

Let's say I have the following filter defined

import jinja2

@jinja2.contextfilter
def my_function(context):
    if context.get('my_var'):
        return "hello"
    else:
        return "world"

Super simplified example, but the point of it is that I have some logic that conditionally returns a value based on some variable passed into the context.

Also, I'm using jinja2 2.11 or something like that, which is why I'm using @contextfilter instead of @pass_context.

I've added this filter to my environment using env.filters['my_function'] = my_function

In rendering the template, I'm calling

template = env.get_template('my_template.html')
template.render({'my_var': 'some_value'})

where the template might look something like

... some html here
{{ my_function }}
... some more html

This doesn't actually return "hello", and instead just is empty/blank.

I managed to get it by passing in a dummy variable

@jinja2.contextfilter
def my_function(context, value):
    .... code is the same

And then in the template, I call it with {{ 'hi' | my_function }}. But obviously this is just a hack and not very desirable.

So my question is, how can I call a jinja2 filter function that only takes the context in as an argument? I've tried {{ my_function() }} which returns the error UndefinedError: 'my_function' is undefined, and {{ | my_function }}, which returns the error TemplateSyntaxError: unexpected '|'`

Or is there some other jinja2 construct I should be using?

Edit: my suspicion is that jinja2 uses the | to identify a filter vs a variable, and since I don't have |, then it tries to just render the variable my_function from the context, and since it doesn't exist in the context, it just outputs an empty string.

CodePudding user response:

Jinja2 calls these kind of functions global functions (like range()), not filters. Just change filters to globals in this line:

env.globals['my_function'] = my_function

And then you can call your function in the templates: {{ my_function() }}.

  • Related