5

I have managed to call python functions from jinja2 by using custom filters, but I can only seem to call functions with one or more parameters. In the following I have had to pass a junk parameter in order to treat ctest as a function rather than a variable.

It also doesn't work if I just call {{ ctest() }}.

Is there a different way to force this to be a function call or should I be using a different approach?

code:

def ctest(stuff):
    return "yeah!"

template_env = jinja2.Environment (loader = jinja2.FileSystemLoader(template_file_root))
#custom filters
template_env.filters['ctest'] = ctest

template:

Working? {{ junk|ctest }}

output:

working? yeah!
chrisst
  • 1,696
  • 5
  • 19
  • 32
  • possible duplicate of [Call a python function from jinja2](http://stackoverflow.com/questions/6036082/call-a-python-function-from-jinja2) – Wooble Jul 25 '12 at 19:41
  • I looked at that question before posting but it doesn't explain how to call filters in the template without parameters. It just explains how to get to the point that I'm already at. – chrisst Jul 25 '12 at 21:00
  • see the second answer: `{{ clever_function() }}` – Wooble Jul 25 '12 at 22:40
  • I tried that also. I'm guessing flask sets up a macro in the background since this doesn't work just through jinja. I also addressed this in my original post, but forgot to modify the funciton names to make sense, i'll edit to be more clear. – chrisst Jul 26 '12 at 00:05
  • 1
    Did you add it to `template_env.globals` before loading any templates, rather than adding it as a filter? – Wooble Jul 26 '12 at 11:06
  • That did the trick! If you add that to the answer I'll gladly accept. – chrisst Jul 27 '12 at 22:20

3 Answers3

1

Summarizing the comments into an answer:

The ability to call functions by adding it to filters isn't really the correct way of going about this since (as Wooble pointed out) I'm not looking to filter anything.

Instead the function just needs to be added to the template_env.globals:

template_globals.filters['ctest'] = ctest
chrisst
  • 1,696
  • 5
  • 19
  • 32
0

Well, they're filters, so they expect to be filtering something. If the motivation is that you want to function to be callable from outside a template without passing any arguments, change the signature to:

def ctest(*args):

and then just ignore the arguments; it will work if it's passed no arguments or any number of them.

Wooble
  • 87,717
  • 12
  • 108
  • 131
  • 1
    The example above works for me, but I would still like to call zero param methods. I would like to be able to call other python libraries without having to write wrapper methods. In particular I am trying to call socket.gethostname(). – chrisst Jul 25 '12 at 19:39
  • Hello from the future lol Have you tried using lambda? i understand essentially it is wrapping a function but less typing than usual. i tired this `tempEnv.globals['test'] = lambda: socket.gethostname()` and it worked. – Evgeny Danilenko Nov 06 '16 at 13:31
  • 'str' object is not callable – stapmoshun Sep 20 '22 at 18:00
0

{{func()}} renders the output. {% call func() %}{%endcall%} calls func() with a caller parameter.

In jinja there really seems to be no straightforward way to call a python function in the template without rendering it or other template side effects. The workaround I came up with is:

{% if func() %}{% endif %}
Roland Puntaier
  • 3,250
  • 30
  • 35