## 问题描述 `app/core/base_model.py` 中 `MappedBase` 的注释明确声明「兼容 SQLite、MySQL 和 PostgreSQL」: ```python class MappedBase(AsyncAttrs, DeclarativeBase): """声明式基类 ... 兼容 SQLite、MySQL 和 PostgreSQL """ ``` 但各业务模块在需要 JSON 列时,若直接硬编码 `sqlalchemy.dialects.postgresql.JSONB`,会在非 PostgreSQL 方言下破坏这一承诺: 1. **SQLite / MySQL 下 `create_all` 直接失败**:`sqlalchemy.exc.CompileError: can't render element of type JSONB`,导致基于 SQLite 的测试套件无法建表启动。 2. **方言差异被下沉到每个业务模型**:每个需要 JSON 列的模块都要自行决定用 `JSONB` 还是通用 `JSON`,容易出现不一致(当前仓库已同时存在 `JSON` 与 `JSONB` 两种用法)。 ## 建议 在基类 `app/core/base_model.py` 提供一个统一的跨方言 JSON 类型,作为各模块定义 JSON 列的唯一入口: ```python from sqlalchemy import JSON from sqlalchemy.dialects.postgresql import JSONB # 跨方言 JSON 类型:PostgreSQL(生产)使用 JSONB,SQLite/MySQL(测试环境)降级为通用 JSON JSONType = JSONB().with_variant(JSON(), "sqlite", "mysql") ``` - PostgreSQL:渲染为 `JSONB`,保留索引 / 操作符能力。 - SQLite / MySQL:降级为通用 `JSON`,保证 `create_all` 与 `autogenerate` 三种方言均可渲染、零漂移。 业务模型统一改为 `mapped_column(JSONType, ...)`,一次性消除方言不一致的隐患。 对应实现见关联 PR。
Activity
fastapiadmin commentedon Oct 22, 2026
统一入口已落地:PR #545(基于 #543 的 rebase 版本)已合并到
dev,backend/app/core/base_model.py现在提供:已实测:PostgreSQL →
JSONB;SQLite / MySQL →JSON;SQLitecreate_all建表与 JSON 读写正常。但 issue 描述的主要故障路径还没修,且实际比描述更早发生 —— 代码生成器会产出非法 import:
GenConstant.DB_TO_SQLALCHEMY['jsonb'] = 'JSONB'(app/common/constant.py:280)import_list.add(f'from sqlalchemy import {映射值}')(gencode/jinja2_template_util.py:701)jsonb列生成模型时,产物首行是from sqlalchemy import JSONB,而JSONB不在顶层sqlalchemy命名空间(实测AttributeError)→ 生成的模块在 import 阶段就失败,比 SQLite 的CompileError更早。同一逻辑还影响
INET / CIDR / MACADDR / Bit(均非顶层导出);Geometry会先加geoalchemy2再被第 701 行覆盖成非法的
from sqlalchemy import Geometry。建议的后续修复(本 issue 暂保持 open):
jsonb映射为JSONType,并从app.core.base_model导入;sqlalchemy.dialects.postgresql/geoalchemy2),避免顶层 import;import,且能在 SQLite 上create_all。fix(generator): 方言类型从正确模块导入,jsonb 统一为跨方言 JSONType
Merge pull request #547 from fastapiadmin/dev
fastapiadmin commentedon Oct 22, 2026
已修复并合并到
dev/master:PR #547(提交30c0e63a)。根因:生成器把 PG 的
jsonb映射为JSONB后拼出from sqlalchemy import JSONB—— 该类型不在顶层sqlalchemy命名空间(实测AttributeError),生成的模型在 import 阶段就失败;同一条逻辑还影响INET / CIDR / MACADDR / Bit / TSVECTOR / TSQUERY,Geometry则会被覆盖成非法的from sqlalchemy import Geometry。修复:
jsonb → JSONType(跨方言:PG→JSONB,SQLite/MySQL→JSON)、bit / bit varying → BITDIALECT_TYPE_IMPORTS:JSONType → app.core.base_model、方言类型 →sqlalchemy.dialects.postgresql、Geometry → geoalchemy2验证:新增 5 个回归测试(PG 方言子进程 + 端到端渲染
ast.parse);红绿验证(还原源码 → 4 个新测试失败,报错即
from sqlalchemy import JSONB);全量pytest102 passed、ruff通过、basedpyright0 errors。feat: 新增跨方言 JSON 类型 JSONType(PG 用 JSONB,SQLite/MySQL 降级 JSON)