web-dev-qa-db-fra.com

Comment puis-je envoyer des variables au modèle Jinja à partir d'un décorateur Flask?

De nombreux itinéraires autour de mon application blueprinted flask devront envoyer des "données de la barre latérale" à jinja.

Je cherche le moyen le plus efficace de le faire. Leur doit être quelque chose de mieux que d'importer ma fonction 'generate_sidebar_data ()' dans chaque plan, en répétant à plusieurs reprises:

var1, var2, var3 = generate_sidebar_data()

puis en les envoyant avec 'render_template':

return render_template('template.html',
                           var1=var1,
                           var2=var2,
                           var3=var3
                      )

Ce que je veux, c'est un décorateur que je puisse mettre avec la route qui fera la même chose que ci-dessus (exécuter la fonction et envoyer les vars à jinja) mais je ne sais pas si c'est possible. Comment envoyer des variables à jinja depuis une fonction décoratrice?

@blueprint.route('/')
@include_sidebar_data
def frontpage():

    return render_template('template.html')
32
chrickso

Je vais proposer quelque chose de plus simple que d'utiliser une méthode de décorateur ou de modèle ou quelque chose comme ça:

def render_sidebar_template(tmpl_name, **kwargs):
    (var1, var2, var3) = generate_sidebar_data()
    return render_template(tmpl_name, var1=var1, var2=var2, var3=var3, **kwargs)

Ouais, juste une fonction. C'est tout ce dont vous avez vraiment besoin, non? Voir this Flask Snippet pour l'inspiration. Il fait essentiellement exactement le même genre de chose, dans un contexte différent.

24
wheaties

Vous pouvez utiliser un processeur de contexte ( http://flask.pocoo.org/docs/api/#flask.Flask.context_processor ):

def include_sidebar_data(fn):
    @blueprint.context_processor
    def additional_context():
        # this code work if endpoint equals to view function name
        if request.endpoint != fn.__name__:
            return {} 
        var1, var2, var3 = generate_sidebar_data()
        return {
            'var1': var1,
            'var2': var2,
            'var3': var3,
        }
    return fn


@blueprint.route('/')
@include_sidebar_data
def frontpage():
    return render_template('template.html')

UPD: J'aime davantage l'exemple suivant et il vaut mieux que le décorateur soit utilisé pour plusieurs fonctions d'affichage:

sidebar_data_views = []


def include_sidebar_data(fn):
    sidebar_data_views.append(fn.__name__)
    return fn


@blueprint.context_processor
def additional_context():
    # this code work if endpoint equals to view function name
    if request.endpoint not in sidebar_data_views:
        return {} 
    var1, var2, var3 = generate_sidebar_data()
    return {
        'var1': var1,
        'var2': var2,
        'var3': var3,
    }


@blueprint.route('/')
@include_sidebar_data
def frontpage():
    return render_template('template.html')
11
tbicr

Vous pouvez créer une fonction décoratrice comme celle-ci:

def include_sidebar_data(fn):
    template_name = fn()
    var1, var2, var3 = generate_sidebar_data()
    def wrapped():
        return render_template(template_name, var1=var2, var2=var2)
    return wrapped

@blueprint.route('/')
@include_sidebar_data
def frontpage():

    return 'template.html'
4
janos