当前位置: 首页 > news >正文

Sqladmin - FastAPI框架下一键生成管理后台

介绍

Github 开源地址:

https://github.com/aminalaee/sqladmin

网站说明链接地址:

https://aminalaee.dev/sqladmin/

一个现代、优雅的 SQLAlchemy 管理后台工具,非常适合用在 FastAPI 项目中

SQLAdmin 是一个基于 FastAPI + SQLAlchemy 构建的管理后台框架,灵感来自于 Django Admin,目标是为 Python 项目提供:

• 🚀 简洁易用的后台界面

• 📋 基于 SQLAlchemy 的模型自动管理

• ⚙️ 快速 CRUD(增删改查)

• ✨ Jinja2 渲染漂亮的 Bootstrap 风格后台

功能描述
🎨 UI基于 Tabler(Bootstrap 风格)构建
🔁 CRUD 自动化自动根据模型生成增删改查
🔍 搜索 / 过滤表字段搜索、过滤支持
🧩 多数据库支持支持 SQLite、PostgreSQL、MySQL 等
🔐 自定义认证可扩展自定义登录(如你用的 AdminAuth)
🧠 异步支持与 FastAPI 完美配合,支持异步视图
🔧 高度可配置支持列隐藏、格式化、标签等配置项

支持models 的类型:

✅ 支持 SQLAlchemy 吗?是,必须基于 SQLAlchemy ORM 模型
✅ 支持 SQLAlchemy 1.x 吗?
✅ 支持 SQLAlchemy 2.x 吗?是,从 sqladmin 0.15.0+ 开始全面支持
❌ 支持 Tortoise ORM 吗?不支持
❌ 支持 Django ORM 吗?不支持

为什么使用?

很多项目都是异步,而异步里面ORM 性能最好的就是 SQLAlchemy 2.0

特性优势是否推荐
✅ 新的 2.0 风格语法更清晰、类型安全,统一 async / sync 用法强烈推荐
✅ 原生异步支持(async_engine)适配 FastAPI、aiohttp 等异步框架
✅ Declarative Mapping 更加清晰不再混用 Base = declarative_base() 和 mapper()
✅ 更强的类型提示支持IDE 友好,调试更舒服
✅ Session 语义改进显式事务控制、更加安全
✅ 官方长期维护方向所有新功能只在 2.x 上更新
特性 / 框架SQLAlchemy 2.0 (async)Tortoise ORMasyncpg (原生驱动)
⭐ 异步支持✅ 原生 async API(2.0 起)✅ 原生 async✅ 原生 async
🎯 ORM 支持✅ 完整 ORM(经典 + 声明式)✅ 类 Django 的 ORM❌ 没有 ORM,需手写 SQL
⚙️ 事务处理✅ async with session.begin()✅ transaction() 上下文✅ 需手动写 SQL + 事务处理
🔧 灵活性✅ 高(支持 ORM + Core)中等(ORM风格较固定)极高(最贴近 SQL)
📚 学习曲线稍高(但文档全)较低,适合 Django 用户中等(需掌握 SQL)
🚀 性能优(合理用 async)优(轻量)最优(直接操作 protocol)
✅ 类型支持✅ Pydantic 配合良好✅ 也能配合 Pydantic 使用❌ 无自动转换,手动处理
🧩 支持的数据库多(PostgreSQL, MySQL, SQLite等)PostgreSQL、MySQL、SQLitePostgreSQL 专用
🔍 社区 & 文档非常成熟(官方长期维护)活跃,偏小众官方是 PostgreSQL 的推荐驱动
你的需求推荐方案
需要强大的 ORM + 类型检查 + 可扩展性SQLAlchemy 2.0 + Async
想快速上手、有 Django ORM 背景Tortoise ORM
要极致性能,手写 SQL 不怕麻烦asyncpg

结合应用

from sqlalchemy import Column, Integer, String, create_engine,Enum as SAEnum,JSON
from sqladmin.authentication import AuthenticationBackend
import json
import hashlib
from sqlalchemy import event

from sqlalchemy.orm import declarative_base
from enum import Enum
from sqlalchemy.ext.hybrid import hybrid_property

Base = declarative_base()
engine = create_engine(
    "sqlite:///example.db",
    connect_args={"check_same_thread": False},
)

# 定义枚举类型
class GenderEnum(str, Enum):
    MALE = "male"
    FEMALE = "female"
    OTHER = "other"

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True)
    name = Column(String)
    gender = Column(SAEnum(GenderEnum), nullable=False, comment="性别")
    password = Column("password", String, nullable=False)  # 真实存储加密后的密码

class JsonConfig(Base):
    __tablename__ = "json_config"

    id = Column(Integer, primary_key=True)
    name = Column(String)
    config = Column(JSON)

Base.metadata.create_all(engine)  # Create tables,后面改了字段需要删除

from fastapi import FastAPI
from sqladmin import Admin, ModelView
from fastapi import Request

app = FastAPI()

class AdminAuth(AuthenticationBackend):
    async def login(self, request: Request) -> bool:
        form = await request.form()
        username, password = form["username"], form["password"]

        # Validate username/password credentials
        # And update session
        if username == "admin" and password == "123456":
            request.session.update({"sqladmin_token": "..."})
            return True
        else:
            return False
        return True

    async def logout(self, request: Request) -> bool:
        # Usually you'd want to just clear the session
        request.session.clear()
        return True

    async def authenticate(self, request: Request) -> bool:
        token = request.session.get("sqladmin_token")

        if not token:
            return False

        # Check the token in depth
        return True

authentication_backend = AdminAuth(secret_key="secret_key")

admin = Admin(app, engine,base_url="/super",authentication_backend=authentication_backend)

class UserAdmin(ModelView, model=User):
    self_md5_salt = "123456"
    column_list = [User.id, User.name,User.gender,User.password]

    # 自定义列标签(让 SQLAdmin UI 显示中文)
    column_labels = {
        "id": "用户 ID",
        "name": "姓名",
        "gender": "性别",
        "password": "密码",
    }
    async def insert_model(self, request: Request, data: dict):
        """拦截插入逻辑,确保 `password` 经过 MD5 加密"""
        raw_password = data.pop("password", None)
        if raw_password:
            data["password"] = hashlib.md5((raw_password+self.self_md5_salt).encode()).hexdigest()
        return await super().insert_model(request, data)

    async def update_model(self, request: Request, pk: str, data: dict):
        """拦截更新逻辑,确保 `password` 经过 MD5 加密"""
        raw_password = data.pop("password", None)
        if raw_password:
            data["password"] = hashlib.md5((raw_password+self.self_md5_salt).encode()).hexdigest()
        return await super().update_model(request, pk, data)

class JsonConfigAdmin(ModelView, model=JsonConfig): 
    column_list = [JsonConfig.id, JsonConfig.name,JsonConfig.config]
    # 前端页面插入的时候 只能使用双引号的json 不能使用单引号的json

admin.add_view(UserAdmin)
admin.add_view(JsonConfigAdmin)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)
# uvicorn test_sqladmin:app --host 127.0.0.1 --port 8000 --reload
# 后台地址: http://127.0.0.1:8000/super

# pip install itsdangerous  sqladmin 

相关文章:

  • Git 钩子:特定操作脚本
  • 深入掌握Spring AOP:从原理到实战的完整指南
  • 在 Qt 中,不带参数或整形的参选的信号能够从 std::thread 发送成功,而带枚举离线的信号却发送失败
  • cocos creator 笔记-路边花草
  • java8循环解压zip文件---实现Excel文件数据追加
  • 慧通测控汽车智能座舱测试技术
  • k8s基础知识总结node+pod(上)
  • CSS语言的双向链表
  • 4、pytest常用插件
  • word中指定页面开始添加页码
  • Python(4)Python函数编程性能优化全指南:从基础语法到并发调优
  • Java设计模式之访问者模式
  • 计算机网络 - OSI 七层模型
  • 笔记:分享如何使用github静态页面搭建个人页面
  • 【2025】基于springboot+uniapp的企业培训打卡小程序设计与实现(源码、万字文档、图文修改、调试答疑)
  • 专访成都昭音科技Jackal:AI内容营销助力中企走向全球
  • 鸿蒙学习笔记(2)-国际化配置、ArkTS简述
  • 【Javaweb】b站黑马视频学习笔记(导览)
  • 多模态大模型Qwen 和 Qwen2 的模型结构、训练方式与数据处理对比分析
  • 安卓应用兼容新方案:Android Translation Layer(ATL)
  • 以色列在加沙发起新一轮强攻,同步与哈马斯展开“无条件谈判”
  • 持续降雨存在落石风险,贵州黄果树景区水帘洞将封闭至6月初
  • 陕西:未来一周高温持续,继续发布冬小麦干热风风险预警
  • 首次公布!我国空间站内发现微生物新物种
  • 圆桌丨新能源车超充技术元年,专家呼吁重视电网承载能力可能面临的结构性挑战
  • 普京批准俄方与乌克兰谈判代表团人员名单