fastapi:jinja2:把登录信息统一传递给模板
一,代码
在middleware中获取用户信息:
# 中间件:全自动解析登录态
# 1. 定义中间件类,必须继承 BaseHTTPMiddleware
class CustomAuthMiddleware(BaseHTTPMiddleware):
async def dispatch(self,
request: Request,
call_next,
):
# 从cookie得到用户信息
current_user = await get_current_user_from_cookie(request)
if current_user is None:
# 将结果挂载到 request.state,方便后续调用
request.state.user = None
request.state.is_authenticated = False
response = await call_next(request)
return response
# 3. 生产环境核心:直接使用全局工厂创建独立的、短暂的会话
try:
async with AsyncSessionLocal() as db:
# 1. 查询用户是否存在
stmt = select(User).where(User.username == current_user['username'])
result = await db.execute(stmt)
user = result.scalar_one_or_none()
if user is None:
cur_user = None
else:
cur_user = {
'username':user.username,
'nickname': user.nickname,
}
except Exception as e:
# 生产环境中务必捕获数据库异常,防止连接泄漏或暴露敏感堆栈
return JSONResponse(status_code=500, content={"detail": "Internal server error"})
# 将结果挂载到 request.state,方便后续调用
request.state.user = cur_user
request.state.is_authenticated = cur_user is not None
response = await call_next(request)
return response
main中应用middleware
# 创建独立隔离的管理后台子应用
admin_app = FastAPI(
title="管理后台系统",
dependencies=[Depends(verify_admin_user)] # 👈 核心:作为子应用全局依赖
)
# 注册全局异常捕获
register_exception_handlers(admin_app)
# 🌟 必须挂载 Session 中间件,flash 消息才得以跨请求保存
admin_app.add_middleware(SessionMiddleware, secret_key="your-secure-secret-key")
# 启用中间件(不使用装饰器)
admin_app.add_middleware(CustomAuthMiddleware)
定义方法,把用户信息数据传递给模板
# 在公共文件中声明模板实例
templates = Jinja2Templates(directory="app/admin/templates")
# -----------------------------------------------------------
# 生产级封装:重写模板渲染方法,自动注入全局变量
def render_template( request: Request, template_name: str,context: dict = None):
if context is None:
context = {}
# 自动把中间件解析出的用户信息,注入到 Jinja2 上下文中
context["request"] = request
context["current_user"] = getattr(request.state, "user", None)
context["is_authenticated"] = getattr(request.state, "is_authenticated", False)
return templates.TemplateResponse(
request=request,
name=template_name,
context=context
)
请求中用自定义的方法返回页面
@router.get("/info")
async def user_info(
request: Request,
# 挂载强制登录依赖,未登录的用户根本进不来
current_user: dict = Depends(admin_login_required)
):
# 获取用户信息
username = current_user['username']
print("username:", username)
cur_user = {
'username': username,
'nickname': '他人不错',
}
return render_template( request,
"account/info.html",
{
"user": cur_user, "title": "登录"
})
html页面:
<!-- index.html -->
{% extends "layout/base.html" %}
<!-- 重写标题块 -->
{% block title %}首页 - 我的网站{% endblock %}
<!-- 填充核心内容块 -->
{% block content %}
<h1>欢迎来到首页!</h1>
<!-- 核心判断:是否登录 -->
{% if is_authenticated %}
<div>当前状态:已登录,用户名:{{current_user.username}}:</div>
<span>欢迎回来,{{ current_user.nickname }} </span>
<a href="/admin/account/logout">退出登录</a>
{% else %}
<div>当前状态:未登录:</div>
<a href="/login">登录</a>
<a href="/register">注册</a>
{% endif %}
<p>当前用户名:{{user['username']}}</p>
{% endblock %}
二,测试效果:

浙公网安备 33010602011771号