外键必须显式声明且方言需支持,否则逆向模型缺失关联和类型。应检查pg_constraint、升级eralchemy≥0.20、转InnoDB引擎、安装扩展包如sqlalchemy-citext,并避免MyISAM或隐式外键。
用 sqlacodegen 逆向生成模型后,ER图连线全是乱的
不是代码没生成对,是默认不带外键约束信息。postgresql 的 information_schema 里查不到隐式外键(比如只靠命名约定、没加 foreign key 约束的字段),sqlacodegen 就不会在 relationship() 里建关联,自然画不出正确连线。
- 先确认数据库里真有显式外键:
SELECT conname, confrelid::regclass FROM pg_constraint WHERE contype = 'f'; - 生成时加
--noclasses参数试试,它会强制扫描约束,比默认模式更靠谱 - 如果表是历史遗留、外键全靠应用层维护,就得手动补
ForeignKeyConstraint到模型里,不然任何 ER 工具都认不出来
用 eralchemy 画图时报错 AttributeError: 'Table' object has no attribute 'schema'
这是 SQLAlchemy 1.4+ 和老版 eralchemy(≤0.19)不兼容的典型症状。新版 SQLAlchemy 把 table.schema 改成 table.schema or None,但旧版 eralchemy 还直接访问属性。
- 升级到
eralchemy>=0.20,它是唯一适配 SQLAlchemy 2.x 的维护分支 - 别用
pip install eralchemy—— 默认装的是死掉的 0.18;得用pip install git+https://github.com/alfred82santa/eralchemy@main - 如果项目锁死了 SQLAlchemy 1.3,那就降级
eralchemy==0.18.3,但注意它不支持JSONB或ARRAY类型,会跳过整张表
MySQL 表用了 ENGINE=MyISAM,逆向完发现关系全丢了
MyISAM 不支持外键约束,所以无论你怎么定义字段名、加注释、写文档,sqlacodegen 或 sqlsoup 都扫不到任何 ForeignKey。它只看约束,不猜业务逻辑。
- 先执行
SHOW CREATE TABLE user_orders;,确认输出里有没有CONSTRAINT关键字 - 转 InnoDB 是最干净的解法:
ALTER TABLE user_orders ENGINE=InnoDB;,再加约束 - 如果不能改引擎,就只能在生成后的模型里手写
relationship(..., primaryjoin="..."),把关联条件硬编码进去
ER 图里字段类型和实际数据库对不上,比如 PostgreSQL 的 citext 显示成 TEXT
这是方言映射缺失的问题。sqlacodegen 依赖 SQLAlchemy 的类型推导,而 citext、ltree、hstore 这些扩展类型需要额外注册方言类,否则就 fallback 成基础类型。
- 安装对应扩展包,比如
pip install sqlalchemy-citext,然后在生成前 import 它 - 生成命令要加
--noinflect,避免把user_profile自动转成Userprofile导致后续映射错乱 - 如果用的是自定义域类型(
CREATE DOMAIN phone AS TEXT CHECK (...)),那基本无解——SQLAlchemy 不解析 domain 定义,只能人工替换模型里的类型声明
外键是不是显式声明的,决定了整个逆向流程能不能走通;而方言支持程度,直接决定你看到的模型是不是“假的”。这两点不提前验,后面花再久调图、改代码,都是在补地基漏掉的洞。










