fastapi:管理后台:退出登录,并封装类似flask的flash函数
一,安装用到的库:
pip install itsdangerous
二,代码
python代码:
main.py中引入SessionMiddleware
# 创建独立隔离的管理后台子应用
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")
temlates.py中添加用到的方法
# app/config/exts.py
from fastapi.templating import Jinja2Templates
from fastapi import FastAPI, Request, Form, status
# 在公共文件中声明模板实例
templates = Jinja2Templates(directory="app/admin/templates")
# ----------------- 🌟 核心:封装 Flash 函数 -----------------
def flash(request: Request, message: str, category: str = "info"):
"""向 Session 中写入一条闪现消息"""
if "_messages" not in request.session:
request.session["_messages"] = []
request.session["_messages"].append({"message": message, "category": category})
def get_flashed_messages(request: Request):
"""从 Session 中取出所有闪现消息,并将其清空(Pop)"""
return request.session.pop("_messages") if "_messages" in request.session else []
# 🌟 将获取消息的方法直接注入到 Jinja2 环境中,这样在 HTML 里就能直接调用
templates.env.globals.update(get_flashed_messages=get_flashed_messages)
# -----------------------------------------------------------
在共用的页面的head部分添加用到的html/css代码:
<body>
<!-- 🌟 核心:直接在 Jinja2 中循环读取并展示闪现消息 -->
{% set messages = get_flashed_messages(request) %}
{% if messages %}
<!-- 1. 浮动在页面最上层的容器 -->
<div id="flash-container" style="position: fixed; top: 20px; left: 50%; transform: translateX(-50%); z-index: 9999; display: flex; flex-direction: column; gap: 10px; align-items: center; width: auto; min-width: 250px; max-width: 90%;">
{% for msg in messages %}
<!-- 2. 圆角、半透明(背景模糊)、阴影、自带淡入淡出动画的提示框 -->
<div class="flash-toast {{ msg.category }}" style="
padding: 12px 24px;
border-radius: 8px;
font-weight: 500;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
backdrop-filter: blur(8px); /* 🌟 毛玻璃效果 */
-webkit-backdrop-filter: blur(8px);
transition: opacity 0.4s ease, transform 0.4s ease; /* 🌟 动画过渡 */
animation: slideIn 0.3s ease forwards;
">
{{ msg.message }}
</div>
{% endfor %}
</div>
<!-- 3. 自定义样式(主要用于控制不同状态的半透明颜色) -->
<style>
/* 淡入动画 */
@keyframes slideIn {
from { opacity: 0; transform: translateY(-20px); }
to { opacity: 1; transform: translateY(0); }
}
/* 成功提示:绿色半透明 */
.flash-toast.success {
background-color: rgba(212, 237, 218, 0.85);
color: #155724;
border: 1px solid rgba(195, 230, 203, 0.5);
}
/* 危险提示:红色半透明 */
.flash-toast.danger {
background-color: rgba(248, 215, 218, 0.85);
color: #721c24;
border: 1px solid rgba(245, 198, 203, 0.5);
}
/* 普通提示:蓝色半透明 */
.flash-toast.info {
background-color: rgba(209, 236, 241, 0.85);
color: #0c5460;
border: 1px solid rgba(190, 229, 235, 0.5);
}
</style>
<!-- 4. 🌟 核心:1秒后自动淡出并销毁的 JS 脚本 -->
<script>
document.addEventListener("DOMContentLoaded", function() {
const container = document.getElementById("flash-container");
if (container) {
// 1000毫秒(1秒)后触发淡出
setTimeout(() => {
const toasts = container.querySelectorAll('.flash-toast');
toasts.forEach(toast => {
toast.style.opacity = '0';
toast.style.transform = 'translateY(-30px)'; // 稍微往上飘走
});
// 等待 400ms 动画结束后,彻底从 DOM 树中移除容器,不占空间
setTimeout(() => container.remove(), 400);
}, 1500);
}
});
</script>
{% endif %}
代码中调用:
# 登出
@router.get("/logout")
def account_logout(
request: Request,
# 挂载强制登录依赖,未登录的用户根本进不来
current_user: dict = Depends(admin_login_required)
):
# 弹出窗口提示已退出
flash(request, "已成功退出登录", category="success")
# 创建response
response = RedirectResponse(
url="/admin/account/login",
status_code=status.HTTP_302_FOUND
)
# 清除浏览器的安全 Cookie
response.delete_cookie(
key=COOKIE_NAME,
path="/", # 必须与你 set_cookie 时的路径一致(默认是 "/")
httponly=True, # 安全策略保持一致
samesite="lax"
)
return response
三,测试效果

浙公网安备 33010602011771号