user2743931
user2743931

Reputation: 312

Flask - use jinja macros without a template

I have a Flask app that looks as follows:

@app.route('/')
def index():
    headline = render_template('headline.html', headline = 'xyz') #-> return <h1>xyz</h1>
    return render_template('page.html', headline = headline) # insert headline html into a page

headline.html is a template which imports a jinja macro from a macro file (macros.html). The macro generates the headline.

headline.html:

{% import 'macros.html' as macros %}
{{ macros.get_headline(headline) }}

macros.html:

{% macro get_headline(headline) %}
<h1>{{ healine }}</h1>
{% endmacro %}

My question is - is it possible to call the macro to get headline without the need to call the template headline.html?

Ideally, I'd like to see

@app.route('/')
def index():
    headline = # somehow call get_headline('xyz') from macros.html
    return render_template('page.html', headline = headline) # insert headline html into a page

Upvotes: 2

Views: 1823

Answers (2)

Kevin E
Kevin E

Reputation: 3576

My question is - is it possible to call the macro to get headline without the need to call the template headline.html?

I hope you figured out your situation. My bet is you'll eventually settle on a better way to do this than what you're proposing, which seems a bit backwards to me, but hey, that's part of the learning process!

Especially for simple text transformation functions that only take a single argument, you may get better mileage from a Python function that you register as a Jinja filter with Environment.filters as described here. It's less syntax all around, and you can use the same function from Python and your Jinja templates in a standard way, without hacks.

That said, I blundered into the .module property on Jinja templates just today. It allows you to call macros from a template as regular Python functions:

macros.html:

{% macro get_headline(headline) -%}
<h1>{{ headline }}</h1>
{%- endmacro %}

test.py:

# these imports not needed for a Flask app
from jinja2 import Environment, FileSystemLoader

# just use `app.jinja_env` for a Flask app
e = Environment(loader=FileSystemLoader('.'))
t = e.get_template('macros.html')

t.module.get_headline('Headline')
# >>> '<h1>Headline</h1>'

I believe (?) this does what you were originally asking, with the app.jinja_env environment that you already have with Flask, and no extra imports.

Upvotes: 2

Sven Eberth
Sven Eberth

Reputation: 3116

Instead of rendering the template from a file, you can render a template from a string. So you can call your macro from a string.

from flask.templating import render_template_string

@app.route('/')
def index():
    headline = render_template_string(
        "{% import 'macros.html' as macros %}"
        "{{ macros.get_headline(headline) }}",
        headline='xyz'
    )
    return render_template('page.html', headline=headline)

(ignoring the typo healine instead of headline in macros.html)

Upvotes: 1

Related Questions