How can I send variables to Jinja template from a Flask decorator?

27,166

Solution 1

I'm going to propose something even simpler than using a decorator or template method or anything like that:

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)

Yup, just a function. That's all you really need, isn't it? See this Flask Snippet for inspiration. It's essentially doing exactly the same sort of thing, in a different context.

Solution 2

You can use a context processor (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: I like the next example more and it is better if the decorator is used for several view functions:

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

Solution 3

You could create a decorator function like this:

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'
Share:
27,166
chrickso
Author by

chrickso

Updated on February 04, 2020

Comments

  • chrickso
    chrickso about 4 years

    Many routes around my blueprinted flask app will need to send 'sidebar data' to jinja.

    I'm looking for the most efficient way to do this. Their has to be something better than importing my 'generate_sidebar_data()' function into every blueprint, repeatedly saying:

    var1, var2, var3 = generate_sidebar_data()
    

    and then sending them with 'render_template':

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

    What I want is a decorator that I can put with the route that will do the same thing the above does (run function and send the vars to jinja) but I don't know if this is possible. How do you send variables to jinja from inside a decorator function?

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