# fastapi-sqlalchemy-gen **Repository Path**: class_g/fastapi-sqlalchemy-gen ## Basic Information - **Project Name**: fastapi-sqlalchemy-gen - **Description**: 基于 FastAPI + SQLAlchemy 的 MySQL 数据库表结构自动检测与 ORM 模型代码生成工具,支持逻辑删除自动过滤、表前缀去除、批量生成。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-23 - **Last Updated**: 2026-05-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Permission Backstage Python 基于 FastAPI + SQLAlchemy 的权限后台管理系统,核心功能为**数据库表结构自动检测与 ORM 模型代码生成**,快速从已有 MySQL 数据库生成 SQLAlchemy 模型文件,免去手动编写模型的工作量。 ## 功能特性 - **数据库表结构检测**:连接 MySQL 数据库,自动获取表字段、主键、索引、外键、表注释等完整结构信息 - **ORM 模型代码生成**:根据表结构自动生成 SQLAlchemy 2.0 风格的模型代码,支持类型映射、逻辑删除字段自动识别 - **基础设施文件自动生成**:首次运行时自动生成 `.env.example`、`conf/db_conf.py`、`models/base.py` 等项目骨架文件 - **逻辑删除自动过滤**:内置 `do_orm_execute` 事件,含 `deleted` 字段的模型 SELECT 查询自动追加 `WHERE deleted = 0` - **表前缀去除**:支持 `--strip-prefix` 去掉表名前缀生成类名(如 `blog_blog` → `Blog`) - **终端彩色输出**:表结构预览和生成代码均有 ANSI 彩色高亮,清晰直观 ## 项目结构 ``` permission-backstage-python/ ├── main.py # 项目入口 ├── pyproject.toml # 项目配置与依赖 ├── .env # 环境变量(数据库连接串,不入库) ├── .env.example # 环境变量模板 ├── conf/ │ ├── __init__.py │ └── db_conf.py # 数据库连接、Session 管理、逻辑删除过滤 ├── models/ │ ├── __init__.py │ ├── base.py # 公共模型基类(BaseModel + SoftDeleteMixin) │ └── blog/ │ └── blog.py # 示例:Blog 模型(由代码生成器生成) └── utils/ ├── db_gen.py # 数据库表结构检查 & 模型代码生成工具 └── templates/ ├── base.py # 模板:models/base.py └── db_conf.py # 模板:conf/db_conf.py ``` ## 环境要求 - Python >= 3.14 - MySQL 数据库 - [uv](https://docs.astral.sh/uv/) 包管理器(推荐) ## 快速开始 ### 1. 安装依赖 使用 uv(推荐): ```bash uv sync ``` 或使用 pip: ```bash pip install -e . ``` ### 2. 配置数据库连接 复制环境变量模板并填入实际数据库连接信息: ```bash cp .env.example .env ``` 编辑 `.env` 文件: ```env DATABASE_URL=mysql+pymysql://root:your_password@localhost:3306/your_database?charset=utf8mb4 ``` ### 3. 运行代码生成 **快速模式** — 编辑 `utils/db_gen.py` 底部的 `TABLES` 列表,然后直接运行: ```bash python utils/db_gen.py ``` **命令行模式** — 指定表名生成: ```bash # 生成单表模型 python utils/db_gen.py blog_blog # 去掉表前缀生成类名(blog_blog → Blog) python utils/db_gen.py blog_blog --strip-prefix blog # 仅打印代码,不写入文件 python utils/db_gen.py blog_blog --print-only # 指定输出路径 python utils/db_gen.py blog_blog -o model/blog.py # 列出数据库所有表名 python utils/db_gen.py --tables ``` ## CLI 参数说明 | 参数 | 缩写 | 说明 | |------|------|------| | `table` | — | 表名,如 `blog_tag`、`blog_blog` | | `--output` | `-o` | 输出文件路径 | | `--dir` | `-d` | 输出目录,默认 `models/` | | `--print-only` | `-p` | 仅打印代码,不写入文件 | | `--bool` | — | 手动指定 Boolean 字段,如 `--bool status deleted` | | `--type` | — | 字段类型覆盖,如 `--type sort:SmallInteger` | | `--strip-prefix` | — | 去掉表名前缀生成类名,如 `--strip-prefix blog` | | `--tables` | — | 列出数据库中所有表名 | ## 快速模式配置 编辑 `utils/db_gen.py` 底部的 `TABLES` 列表进行批量生成配置: ```python TABLES = [ {"table": "blog_blog", "strip_prefix": "blog"}, {"table": "blog_tag", "strip_prefix": "blog"}, {"table": "sys_user", "bool": ["status"], "strip_prefix": "sys"}, {"table": "sys_role", "type": ["sort:SmallInteger"], "strip_prefix": "sys"}, ] ``` 支持的配置项: | 键 | 说明 | 示例 | |----|------|------| | `table` | 表名(必填) | `"blog_blog"` | | `strip_prefix` | 去掉表前缀 | `"blog"` | | `bool` | Boolean 字段名列表 | `["status", "deleted"]` | | `type` | 字段类型覆盖 | `["sort:SmallInteger"]` | | `print_only` | 仅打印不写入 | `True` | ## 核心模块说明 ### `utils/db_gen.py` — 代码生成工具 包含以下核心组件: - **`DBInspector`**:数据库表结构检查器,连接数据库并获取表字段、主键、索引、外键等信息 - **`generate_model_code()`**:根据表结构生成 SQLAlchemy 模型代码字符串 - **`gen_model()`**:一键生成入口,自动检测表结构 → 生成代码 → 写入模型文件 - **`_ensure_project_infra()`**:自动生成项目基础设施文件(`.env.example`、`conf/db_conf.py`、`models/base.py`) #### SQLAlchemy 类型映射 | MySQL 类型 | SQLAlchemy 类型 | |-----------|----------------| | VARCHAR, CHAR | String | | TEXT, LONGTEXT, MEDIUMTEXT, TINYTEXT | Text | | INTEGER, TINYINT | Integer | | BIGINT | BigInteger | | SMALLINT | SmallInteger | | FLOAT, DOUBLE | Float | | DECIMAL, NUMERIC | Numeric | | DATE | Date | | DATETIME, TIMESTAMP | DateTime | | BOOLEAN | Boolean | | BLOB | LargeBinary | | JSON | JSON | | ENUM | Enum | ### `conf/db_conf.py` — 数据库连接与会话管理 提供以下功能: - **`engine`**:SQLAlchemy 连接池引擎(连接池大小 10,最大溢出 20,连接回收 3600s) - **`Base`**:所有 ORM 模型的声明基类 - **`db_session`**:线程安全的 Session 工厂(`scoped_session`) - **`get_db()`**:FastAPI 依赖注入函数,每个请求获取独立 Session,请求结束自动释放 - **逻辑删除自动过滤**:通过 `do_orm_execute` 事件,含 `deleted` 字段的模型 SELECT 自动追加 `WHERE deleted = 0` ### `models/base.py` — 公共模型基类 - **`BaseModel`**:提供 `id`(UUID 字符串主键)、`create_time`、`update_time` 三个公共字段 - **`SoftDeleteMixin`**:提供 `deleted` 字段(默认 `False`),继承后自动参与逻辑删除过滤 #### 使用方式 ```python from conf.db_conf import Base from models.base import BaseModel, SoftDeleteMixin # 需要逻辑删除的模型 class Blog(Base, BaseModel, SoftDeleteMixin): # 自动拥有 id、create_time、update_time、deleted __tablename__ = "blog_blog" title = Column(String(50), comment="标题") # 不需要逻辑删除的模型 class Tag(Base, BaseModel): # 只有 id、create_time、update_time,无 deleted __tablename__ = "blog_tag" name = Column(String(50), comment="标签名") ``` ## 逻辑删除机制 ### 约定 - `deleted` 字段:`0`(`False`)= 未删除,`1`(`True`)= 已删除 - 模型定义时必须加 `default=False`,确保新增记录 `deleted=0` - 恢复操作使用 Core API(`db.execute(update(...))`)绕过 ORM 事件 ### 自动过滤原理 `conf/db_conf.py` 中注册了 `do_orm_execute` 事件监听: 1. 当 ORM 执行 `SELECT` 查询时自动触发 2. 检查查询涉及的所有模型实体(mapper) 3. 如果模型定义了 `deleted` 字段,自动在语句层面追加 `WHERE deleted = 0 OR deleted IS NULL` 4. 使用 `OR deleted IS NULL` 兼容历史脏数据 ### 恢复已删除数据 使用 Core API 绕过 ORM 事件监听: ```python from sqlalchemy import update # 绕过自动过滤,直接更新 deleted 字段 db.execute( update(Blog).where(Blog.id == blog_id).values(deleted=False) ) db.commit() ``` ## 依赖说明 | 依赖 | 版本 | 说明 | |------|------|------| | fastapi | >=0.136.1 | Web 框架 | | sqlalchemy | >=2.0.49 | ORM 框架 | | pymysql | >=1.2.0 | MySQL 驱动 | | python-dotenv | >=1.2.2 | 环境变量加载 | | uvicorn | >=0.47.0 | ASGI 服务器 | ## 开发指南 ### 生成新表的模型 1. 确保数据库中已存在目标表 2. 配置 `.env` 中的 `DATABASE_URL` 3. 运行生成命令:`python utils/db_gen.py your_table_name --strip-prefix your_prefix` 4. 生成的模型文件自动写入 `models/` 对应目录 ### 自定义模板 模板文件存放在 `utils/templates/` 目录: - `base.py`:`models/base.py` 的模板 - `db_conf.py`:`conf/db_conf.py` 的模板(使用 `__DEFAULT_DATABASE_URL__` 占位符) 修改模板文件后,新生成的项目会使用更新后的模板(已有文件不会被覆盖)。