How to import custom jinja2 filters from another file (and using Flask)?


Question

I have a jinja_filters.py file with a few dozen custom filters I've written. Now I have multiple Flask apps that need to use these filters. (I'm not sure if my problem is Flask-specific or not.)

One hacky way to accomplish what I want is to do:

app = Flask(__name__)

import jinja_filters

@app.template_filter('filter_name1')
def filter_name1(arg):
    return jinja_filters.filter_name1(arg)

@app.template_filter('filter_name2')
def filter_name2(arg):
    return jinja_filters.filter_name2(arg)

...

What's the "right" way to do this?

EDIT: Ideally, I wouldn't have to list each filter name. So when I add a new filter to jinja_filters.py I don't have to update any other code -- all my apps would be able to use it right away.

1
18
8/4/2014 6:17:25 AM

Accepted Answer

Where ever you're setting up your app object (app.py, perhaps), you only need to import your custom filters and then modify the Jinja environment attribute.

import jinja_filters

app = Flask(__name__)
app.jinja_env.filters['filter_name1'] = jinja_filters.filter_name1
app.jinja_env.filters['filter_name2'] = jinja_filters.filter_name2

and so on.

Another possibility is to use the inspect module to find all the methods in jinja_filters like so:

from inspect import getmembers, isfunction
import jinja_filters

app = Flask(__name__)

my_filters = {name: function 
                for name, function in getmembers(jinja_filters)
                if isfunction(function)}

app.jinja_env.filters.update(my_filters)

That code is untested, but the idea is to build a dictionary of function names and functions that exist in your jinja_filters files and then update the Jinja environment's filters dictionary with your filters.

26
9/5/2012 9:21:45 PM

There is a recommended way of doing this using Flask blueprints. One of it's use cases is this functionality specifically:

  • Provide template filters, static files, templates, and other utilities through blueprints. A blueprint does not have to implement applications or view functions.

You just need to create a flask.Blueprint object and use it to register your filters in a similar way as you would with flask.Flask app object, using the Blueprint.app_template_filter decorator or Blueprint.add_app_template_filter method.

# filters.py

import jinja2
import flask

blueprint = flask.Blueprint('filters', __name__)

# using the decorator
@jinja2.contextfilter
@blueprint.app_template_filter()
def filter1(context, value):
    return 1

# using the method
@jinja2.contextfilter
def filter2(context, value):
    return 2

blueprint.add_app_template_filter(filter2)

Then you just need to register the blueprint on your app object:

# app.py

import flask
import filters

app = flask.Flask(__name__)
app.register_blueprint(filters.blueprint)

And voilĂ , the filters are registered.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon