使用Flask向所有Jinja2模板传递变量

20

我在我的webapp导航系统中有一个表格,每次渲染页面时都会填充最新的信息。如何避免在每个view中都放置以下代码?

def myview():
    mydict = code_to_generate_dict() 
    return render_template('main_page.html',mydict=mydict)

mydict 用于填充表格。该表格将显示在每个页面上。

3个回答

37
你可以使用 Flask上下文处理器将全局变量注入到Jinja模板中。
以下是一个示例:
@app.context_processor
def inject_dict_for_all_templates():
    return dict(mydict=code_to_generate_dict())

为了自动将新变量注入到模板上下文中,Flask 中存在上下文处理器。上下文处理器在模板呈现之前运行,并且具有向模板上下文中注入新值的能力。上下文处理器是一个返回字典的函数。然后,该字典的键和值与应用程序中所有模板的模板上下文合并:

1
为了不让其他人感到困惑,也许可以提醒一下 Flask 正在寻找一个 dict 来返回,无论我要注入的变量是一个 stringlist 还是任何其他数据类型(包括 dict)。 - Brian Leach
Josh J,你说得没错,但我在处理有多个视图文件的项目时遇到了问题。我该如何在更多的文件中实现context_processor?context_processor必须存在于所有文件中吗?还是我可以使用更系统化的解决方案?谢谢。 - lukassliacky
1
context_processor在Flask应用程序对象上,因此它适用于该应用程序处理的任何视图。如果您有多个应用程序,则需要重复此操作。 - Josh J
@JoshJ 感谢您的及时回答。我的意思是一个具有更复杂结构和更多视图文件的项目。例如:app/customer/views_customer.py, app/results/views_results.py 我是否需要为每个视图文件使用单独的 context_processor - lukassliacky
1
每个 Flask 实例 (app = Flask(...) ) 只有一个。如果这些视图都由先前的 app 服务,则它们共享上下文。 - Josh J
1
谢谢,我解决了_generic menu_的问题 :) - Milovan Tomašević

1

您可以传递一个函数来代替装饰器,该函数将作为必要的上下文处理器。

app = Flask(__name__)
app.context_processor(templatetags)

def templatetags():
    def format_price(amount, currency="€"):
        return f"{amount:.2f}{currency}"

    return dict(
        format_price=format_price,
    )

'index.html'

{{ format_price(0.33) }}

0

编写自己的渲染方法以避免重复代码。然后每当您需要呈现模板时,请调用它。

def render_with_dict(template):
    mydict = code_to_generate_dict() 
    return render_template(template, mydict=mydict)

def myview():
    return render_with_dict('main_page.html')

Josh的回答并不要求我修改所有现有的模板。 - Brian Leach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接