【问题标题】:How can I send variables to Jinja template from a Flask decorator?如何从 Flask 装饰器将变量发送到 Jinja 模板?
【发布时间】:2013-03-29 08:17:18
【问题描述】:

我的蓝图烧瓶应用程序周围的许多路线都需要将“侧边栏数据”发送到 jinja。

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

var1, var2, var3 = generate_sidebar_data()

然后使用“render_template”发送它们:

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

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

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

    return render_template('template.html')

【问题讨论】:

    标签: python templates flask decorator jinja2


    【解决方案1】:

    我将提出一些比使用装饰器或模板方法或类似方法更简单的方法:

    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)
    

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

    【讨论】:

    • 非常干净——我喜欢。
    • @dmonopoly 说了什么。即使在 2016 年,仍然很有帮助。谢谢,+1。
    • @gf_ 即使在 2018 年
    • 我不认为它更简单,如果我有多个视图需要相同的数据怎么办?无需在每个变量上都将这些变量重写为 render_template
    【解决方案2】:

    您可以使用上下文处理器 (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:我更喜欢下一个例子,如果装饰器用于多个视图功能会更好:

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

    【讨论】:

    • 我确实玩过 context_processor,但我挂断了“@blueprint”部分。我的装饰器不在蓝图中,因此没有可用的“@app”或“@blueprint”
    • 所以使用@app 装饰器,它为所有带有任何蓝图的应用程序添加上下文。
    • @tbicr 老评论,我知道。但是您在示例中拼错了“blueprint”。
    【解决方案3】:

    你可以像这样创建一个装饰器函数:

    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'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-09
      相关资源
      最近更新 更多