1. 简介
SQLAdmin 是一个用于 Starlette/FastAPI 应用的管理界面生成库。它提供了一个简单而强大的方式来为你的数据库模型创建CRUD(创建、读取、更新、删除)管理界面。SQLAdmin 支持多种数据库后端,包括 SQLAlchemy、SQLModel、Tortoise ORM 等。
本文档将详细介绍如何在项目中使用 SQLAdmin。
2. 基础配置
2.1 初始化配置
在 main.py 中,我们需要进行以下基础配置:
from sqladmin import Admin
from sqlalchemy import create_engine
# 创建数据库引擎
engine = create_engine(
"your_database_url",
pool_pre_ping=True,
echo=True # 启用SQL语句日志
)
# 创建Admin实例
admin = Admin(
app, # FastAPI 应用实例
engine, # SQLAlchemy 引擎
base_url="/admin", # 管理界面的基础URL
title="管理后台", # 管理界面标题
)
2.2 认证配置
SQLAdmin 提供了灵活的认证机制,通过继承 AuthenticationBackend 类来实现自定义认证。以下是一个完整的认证配置示例:
from sqladmin.authentication import AuthenticationBackend
from starlette.requests import Request
import logging
# 设置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class AdminAuth(AuthenticationBackend):
async def login(self, request: Request) -> bool:
"""
处理登录请求
- 从表单中获取用户名和密码
- 验证凭据
- 设置会话状态
"""
try:
form = await request.form()
username, password = form["username"], form["password"]
# 验证逻辑(示例)
# 实际应用中应该:
# 1. 从数据库验证用户
# 2. 使用安全的密码哈希
# 3. 实现更复杂的安全措施
if username == "admin" and password == "admin123":
# 设置会话状态
request.session["admin_auth"] = True
request.session["username"] = username
return True
# 登录失败处理
request.session["login_message"] = "用户名或密码错误"
return False
except Exception as e:
logger.error(f"Login error: {str(e)}")
request.session["login_message"] = "登录时发生错误"
return False
async def logout(self, request: Request) -> bool:
"""
处理登出请求
- 清除会话
- 记录日志
"""
try:
request.session.clear()
return True
except Exception as e:
logger.error(f"Logout error: {str(e)}")
return False
async def authenticate(self, request: Request) -> bool:
"""
验证用户是否已认证
- 检查会话状态
- 记录调试日志
"""
try:
return request.session.get("admin_auth", False)
except Exception as e:
logger.error(f"Authentication error: {str(e)}")
return False
# 在 FastAPI 应用中配置认证
from starlette.middleware.sessions import SessionMiddleware
# 1. 添加会话中间件
app.add_middleware(
SessionMiddleware,
secret_key="your-secret-key-here", # 使用安全的密钥
session_cookie="admin-session", # 自定义会话 cookie 名称
max_age=None # 会话过期时间,None 表示浏览器关闭时过期
)
# 2. 配置 Admin 认证
admin = Admin(
app,
engine,
authentication_backend=AdminAuth(secret_key="your-admin-secret-key"),
base_url="/admin",
title="管理后台"
)
认证配置的关键点:
- 会话管理:
- 使用
SessionMiddleware管理用户会话 - 配置安全的密钥和会话选项
- 可以自定义会话 cookie 的名称和过期时间
- 认证类实现:
login(): 处理登录请求,验证用户凭据logout(): 处理登出请求,清除会话authenticate(): 验证用户是否已认证
- 安全建议:
- 使用环境变量存储密钥
- 实现数据库用户验证
- 使用安全的密码哈希算法
- 添加登录失败次数限制
- 实现密码策略
- 记录详细的安全日志
- 错误处理:
- 捕获并记录所有可能的异常
- 提供用户友好的错误消息
- 维护详细的日志记录
3. 创建管理视图
3.1 基础视图类
在 views/base.py 中,我们定义了一个基础视图类:
from sqladmin import ModelView
class BaseModelView(ModelView):
# 自定义模板
list_template = "admin/list.html"
create_template = "admin/create.html"
edit_template = "admin/edit.html"
details_template = "admin/details.html"
# 默认配置
can_create = True # 允许创建
can_edit = True # 允许编辑
can_delete = True # 允许删除
can_view_details = True # 允许查看详情
can_export = True # 允许导出
page_size = 20 # 每页显示记录数
column_default_sort = ("id", True) # 默认排序,按照id倒序排序
3.2 创建模型视图
对于每个数据库模型,我们可以创建对应的管理视图:
class UserAdmin(BaseModelView, model=User):
# 视图名称
name = "用户"
name_plural = "用户管理"
# 分类
category = "用户管理"
# 显示的列
column_list = ["id", "username", "email", "created_at"]
# 列标签映射
column_labels = {
"id": "ID",
"username": "用户名",
"email": "邮箱",
"created_at": "创建时间"
}
4. 高级功能
4.1 自定义列表显示
可以通过重写 get_list_value 方法来自定义列表页面的值显示。这个方法接收两个参数:
-
model: 当前数据行的模型实例 -
name: 当前列的名称def get_list_value(self, model, name): """ 自定义列表显示值
参数: model: SQLAlchemy 模型实例,比如 User 对象 name: 列名,比如 'status', 'username' 等 示例: 如果 model 是 User 实例,name 是 'status' 则 getattr(model, name) 相当于 model.status """ # getattr(object, attribute) 等同于 object.attribute value = getattr(model, name) # 根据不同的列名进行不同的处理 if name == 'status': return '启用' if value else '禁用' elif name == 'type': # 处理类型枚举 type_map = { 1: '个人用户', 2: '企业用户', 3: 'VIP用户' } return type_map.get(value, '未知类型') elif name == 'created_at': # 格式化日期时间 return value.strftime('%Y-%m-%d %H:%M:%S') if value else '' elif name == 'amount': # 格式化金额 return f'¥{value:.2f}' if value else '¥0.00' # 如果没有特殊处理,返回原始值 return value实际应用示例
class UserAdmin(BaseModelView, model=User): name = "用户" name_plural = "用户管理"
def get_list_value(self, model, name): value = getattr(model, name) # 处理用户状态显示 if name == 'status': status_map = { 0: '<span class="badge bg-danger">禁用</span>', 1: '<span class="badge bg-success">启用</span>' } return status_map.get(value, '') # 处理用户类型显示 elif name == 'user_type': type_map = { 'personal': '个人', 'business': '企业', 'admin': '管理员' } return type_map.get(value, value) return value
这个方法的常见用途包括:
- 格式化显示:
- 日期时间格式化
- 数字金额格式化
- 状态文本转换
- 值映射转换:
- 将数字状态转为文本
- 将代码转为可读文本
- 处理枚举值显示
- HTML 渲染:
- 添加样式标签
- 显示图标或徽章
- 创建链接
- 数据处理:
- 数据脱敏(如手机号、邮箱)
- 数据截断(长文本)
- 条件格式化
注意事项:
- 返回的 HTML 内容需要使用
Markup类包装,以避免被转义 - 处理空值和异常情况
- 考虑性能影响,避免在此方法中进行复杂的数据库查询
4.2 表单字段定制
可以使用 form_overrides 和 form_widget_args 来定制表单字段:
class ArticleAdmin(BaseModelView, model=Article):
form_overrides = {
'content': TextAreaField
}
form_widget_args = {
'content': {
'rows': 10
}
}
4.3 分组管理
可以通过 category 属性对管理视图进行分组:
GROUP_NAMES = {
"user": "用户管理",
"article": "文章管理",
"system": "系统管理"
}
class UserAdmin(BaseModelView, model=User):
category = GROUP_NAMES["user"]
5. 注册视图
在 main.py 中注册所有管理视图:
# 注册单个视图
admin.add_view(UserAdmin)
# 批量注册视图
for view_class in [
UserAdmin,
ArticleAdmin,
CategoryAdmin
]:
admin.add_view(view_class)
6. 最佳实践
- 视图组织:
- 将相关的视图放在同一个分组下
- 使用清晰的命名和标签
- 合理设置每个视图的权限
- 安全性:
- 始终启用认证
- 使用环境变量存储敏感信息
- 根据需要限制视图权限
- 性能优化:
- 合理设置每页显示记录数
- 只显示必要的列
- 使用适当的过滤器和排序
- 用户体验:
- 提供清晰的列标签
- 添加必要的帮助文本
- 自定义复杂数据的显示方式
7. 常见问题
- 如何自定义列表显示?
- 使用
get_list_value方法 - 使用
column_formatters定义格式化函数
- 如何添加自定义操作?
- 继承
BaseModelView并添加自定义方法 - 使用
@expose()装饰器定义新的路由
- 如何处理关联数据?
- 使用
form_ajax_refs实现异步加载 - 使用
inline_models实现内联编辑
8. 总结
SQLAdmin 是一个功能强大的管理界面工具,通过合理的配置和使用,可以快速构建出易用的后台管理系统。在使用过程中,要注意:
- 遵循最佳实践
- 注意安全性
- 关注性能
- 重视用户体验
希望本文档能帮助你更好地使用 SQLAdmin!