2012-09-05 3 views
16

Ich habe eine jinja_filters.py Datei mit einigen Dutzend benutzerdefinierten Filtern, die ich geschrieben habe. Jetzt habe ich mehrere Flask-Apps, die diese Filter verwenden müssen. (Ich bin nicht sicher, ob mein Problem Flask-spezifisch ist oder nicht.)Wie importiere ich benutzerdefinierte jinja2 Filter aus einer anderen Datei (und verwende Flask)?

One hacky Weg zu erreichen, was ich will, ist zu tun:

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) 

... 

Was ist der „richtige“ Weg, dies zu tun?

EDIT: Im Idealfall müsste ich nicht jeden Namen filtern. Wenn ich also einen neuen Filter zu jinja_filters.py hinzufüge, muss ich keinen anderen Code aktualisieren - alle meine Apps könnten ihn sofort verwenden.

Antwort

25

Wo immer Sie Ihr App-Objekt (app.py, vielleicht) einrichten, müssen Sie nur Ihre benutzerdefinierten Filter importieren und dann das Jinja-Umgebungsattribut ändern.

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 

und so weiter.

Eine andere Möglichkeit ist es, das inspect Modul zu verwenden, um alle Methoden in jinja_filters wie so zu finden:

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) 

Dieser Code ungetestet ist, aber die Idee ist es, ein Wörterbuch von Funktionsnamen und Funktionen zu erstellen, die in existieren Ihre jinja_filters Dateien und aktualisieren Sie dann das Filter-Wörterbuch der Jinja-Umgebung mit Ihren Filtern.

+0

Das ist definitiv besser als das, was ich habe. Aber gibt es eine Möglichkeit, dass ich nicht jeden Filternamen explizit aufführen muss? –

+0

Ich aktualisierte meine Antwort mit einer anderen Lösung, die dynamisch die Filter mit dem 'inspect' Modul hinzufügen konnte. – aezell

+1

Nun, es macht den Job gut gemacht :) Aber ich kann immer noch nicht glauben, dass die Autoren von Jinja2/Flask keine prägnantere Möglichkeit hatten, dies zu tun. (Ich werde Ihre Antwort in ein paar Tagen markieren, wenn niemand sonst hereinkommt.) –

28

Es wird empfohlen, Flask blueprints zu verwenden. speziell eines seiner Anwendungsfälle ist diese Funktionalität:

  • Template Filter, statische Dateien, Vorlagen und andere Dienstprogramme durch Pläne sorgen. Ein Blueprint muss keine Anwendungen oder Ansichtsfunktionen implementieren.

Sie brauchen nur ein flask.Blueprint Objekt zu erstellen und verwenden Sie sie Ihre Filter in ähnlicher Weise zu registrieren, wie Sie es mit flask.Flask App-Objekt, den Blueprint.app_template_filter Dekorateur oder Blueprint.add_app_template_filter Methode.

# 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) 

Dann brauchen Sie nur den Bauplan auf dem App-Objekt registrieren:

# app.py 

import flask 
import filters 

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

Und voilà, werden die Filter registriert.

Verwandte Themen