在FastAPI中设置全局变量供模板调用

在FastAPI中,你可以通过几种方式设置全局变量让模板(如Jinja2)调用:

方法1:使用app.state

from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates

app = FastAPI()
templates = Jinja2Templates(directory="templates")

设置全局变量

app.state.site_name = "我的网站"
app.state.company = "ABC公司"

在路由中使用

@app.get("/") async def home(request: Request): return templates.TemplateResponse("index.html", {"request": request}) 在模板中可以直接访问:

<h1>欢迎来到{{ request.app.state.site_name }}</h1>
<p>版权所有 © {{ request.app.state.company }}</p>
方法2:使用中间件添加全局变量
@app.middleware("http")
async def add_global_vars(request: Request, call_next):
    response = await call_next(request)
    request.state.global_vars = {
        "site_name": "我的网站",
        "company": "ABC公司"
    }
    return response

在模板中:

<h1>欢迎来到{{ request.state.global_vars.site_name }}</h1>
方法3:使用模板上下文处理器
from fastapi.templating import Jinja2Templates

templates = Jinja2Templates(directory="templates")

# 添加上下文处理器
def global_context(request: Request):
    return {
        "site_name": "我的网站",
        "company": "ABC公司"
    }

templates.env.globals.update(global_context=global_context)

在模板中直接使用:

<h1>欢迎来到{{ site_name }}</h1>
方法4:在每次渲染模板时传递变量
@app.get("/")
async def home(request: Request):
    context = {
        "request": request,
        "site_name": "我的网站",
        "company": "ABC公司"
    }
    return templates.TemplateResponse("index.html", context)

最佳实践建议

对于不常变化的全局变量,推荐使用app.state或模板上下文处理器

对于需要根据请求变化的变量,使用中间件或每次渲染时传递

确保变量名称不会与路由函数返回的变量冲突

注意:使用全局变量时要小心线程安全问题,确保变量是不可变的或线程安全的。

在 FastAPI 中使用 Tortoise ORM 设置全局变量并在模板中调用

要在 FastAPI 中使用 Tortoise ORM 设置全局变量并在模板(如 Jinja2)中调用,你可以按照以下步骤操作:

1. 设置 Tortoise ORM 并创建全局变量

首先,在你的 FastAPI 应用启动时初始化 Tortoise ORM,并设置全局变量:

from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from tortoise import Tortoise

app = FastAPI()

配置模板

templates = Jinja2Templates(directory="templates")

全局变量字典

global_vars = {
    'site_name': '我的网站',
    'current_year': 2025
}

async def init_db():
    # 初始化 Tortoise ORM
    await Tortoise.init(
        db_url='sqlite://db.sqlite3',
        modules={'models': ['app.models']}
    )
    # 生成模式(可选)
    await Tortoise.generate_schemas()

@app.on_event("startup")
async def startup_event():
    await init_db()
    # 将全局变量添加到模板环境中
    templates.env.globals.update(global_vars)

2. 在路由中使用模板并访问全局变量

在你的路由中,可以直接在模板中使用这些全局变量:

@app.get("/")
async def home(request: Request):
    # 从数据库获取数据
    from app.models import User
    users = await User.all()

    return templates.TemplateResponse(
        "index.html",
        {
            "request": request,
            "users": users,
            # 可以在这里覆盖全局变量或添加页面特定变量
            "page_title": "首页"
        }
    )

3. 在模板中使用全局变量

在 templates/index.html中,你可以这样使用全局变量:

<!DOCTYPE html>
<html>
<head>
    <title>{{ page_title }} - {{ site_name }}</title>
</head>
<body>
    <h1>欢迎来到 {{ site_name }}</h1>
    <p>© {{ current_year }} 版权所有</p>

    <h2>用户列表</h2>
    <ul>
        {% for user in users %}
        <li>{{ user.username }}</li>
        {% endfor %}
    </ul>
</body>
</html>

4. 高级用法:使用依赖项注入

如果你需要在多个路由中访问相同的全局数据,可以使用 FastAPI 的依赖项系统:

from fastapi import Depends

async def get_global_data():
    return {
        'stats': await SomeModel.all().count(),
        'featured_items': await Item.filter(featured=True).all()
    }

@app.get("/about")
async def about_page(
    request: Request,
    global_data: dict = Depends(get_global_data)
):
    return templates.TemplateResponse(
        "about.html",
        {
            "request": request,
            **global_data
        }
    )

注意事项

​​线程安全​​:确保你的全局变量是线程安全的,或者在访问时进行适当的同步。

​​数据库连接​​:Tortoise ORM 是异步的,确保在需要时正确打开和关闭连接。

​​性能​​:频繁访问数据库获取全局数据可能会影响性能,考虑使用缓存。

​​模板上下文处理器​​:Jinja2 也支持上下文处理器,可以用于更复杂的场景。

通过这种方式,你可以在 FastAPI 模板中轻松使用 Tortoise ORM 的数据和全局变量。