Python 如何从 Flask 装饰器向 Jinja 模板发送变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15858947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 21:12:12  来源:igfitidea点击:

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

pythontemplatesflaskdecoratorjinja2

提问by chrickso

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

我的蓝图烧瓶应用程序周围的许多路线需要将“侧边栏数据”发送到 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:

我正在寻找最有效的方法来做到这一点。它们必须比将我的 'generate_sidebar_data()' 函数导入每个蓝图中更好,反复说:

var1, var2, var3 = generate_sidebar_data()

and then sending them with 'render_template':

然后用“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?

我想要的是一个装饰器,我可以将它与路由一起放置,该路由将执行与上述相同的操作(运行函数并将 vars 发送到 jinja),但我不知道这是否可行。如何从装饰器函数内部向 jinja 发送变量?

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

    return render_template('template.html')

采纳答案by wheaties

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 thisFlask Snippet for inspiration. It's essentially doing exactly the same sort of thing, in a different context.

是的,只是一个函数。这就是你真正需要的,不是吗?请参阅Flask Snippet 以获取灵感。它本质上是在不同的上下文中做完全相同的事情。

回答by janos

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'

回答by tbicr

You can use a context processor (http://flask.pocoo.org/docs/api/#flask.Flask.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:

UPD:我更喜欢下一个例子,如果装饰器用于多个视图函数会更好:

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