最常见原因是手动修改alembic脚本后未同步Python模型类,或autogenerate时env.py过滤逻辑未清理;SQLAlchemy只认类定义,不反推表结构。
SQLAlchemy 模型没更新,迁移脚本跑完但 db.Model 还是旧字段
模型类和数据库表不同步,最常见原因是手动改了 alembic 脚本但忘了同步 python 类,或者用了 autogenerate 却没清空 env.py 里的过滤逻辑。sqlalchemy 不会自动读取当前表结构反推模型——它只认你写的类定义。
- 运行
alembic revision --autogenerate -m "add user.phone"前,先确认你的模型文件(比如models.py)里User类已加上phone = Column(String) - 如果改的是已有字段类型(比如
String(50)→String(200)),autogenerate默认不检测这类变更,得加参数:alembic revision --autogenerate -m "resize phone" --sql看生成的 SQL 是否含ALTER COLUMN,再手动补进脚本 - 团队中有人直接在数据库执行
ALTER TABLE而没走迁移,会导致alembic history和实际 schema 脱节——下次autogenerate可能报错或漏生成
Django makemigrations 检测不到字段删减或重命名
Django 的迁移检测依赖模型定义对比,但它不会主动猜“这个字段是不是被重命名了”,而是当成“删一个 + 加一个”,导致数据丢失。尤其团队协作时,A 删了 old_name、B 加了 new_name,各自 makemigrations 后合并,可能产生冲突迁移。
- 字段重命名必须显式声明:
python manage.py makemigrations --name rename_old_to_new --empty myapp,然后在生成的空文件里手动写migrations.RenameField(...) - 删除字段前,确认所有分支都已合入该字段的最后使用逻辑;否则别人基于旧模型写的代码在新迁移后会直接
AttributeError -
makemigrations --dry-run是必做步骤——它会输出将要生成的迁移内容,避免提交一个“空迁移”或“逆向操作迁移”
Go + GORM v2 模型结构变更后 AutoMigrate 不生效
AutoMigrate 默认只建表、加字段、改非空约束,不会删字段、改字段类型(如 int → string)、或删索引。多人协作时,有人本地用 AutoMigrate 覆盖线上结构,极易引发生产事故。
- 开发环境可开
gorm.Config{DisableForeignKeyConstraintWhenMigrating: true}避免外键干扰,但上线前必须关掉 - 字段类型变更必须手写
db.Migrator().AlterColumn(),且注意 PostgreSQL/MySQL 对ALTER COLUMN TYPE的兼容性差异(比如 MySQL 8.0+ 才支持TEXT→MEDIUMTEXT直接改) - 永远不要在生产环境调用
AutoMigrate——它没有版本锁、不记录执行状态,一次失败就可能卡死后续迁移
模型变更后 CI 流水线里单元测试全挂,但本地正常
根本原因通常是测试数据库没重置或迁移没按序执行。CI 环境一般用临时 DB(如 test_db_12345),但迁移脚本若依赖全局状态(比如硬编码 postgres://... 或跳过 upgrade base),就会漏执行早期迁移。
- CI 脚本里数据库初始化必须包含三步:
createdb test_db→alembic upgrade head(或python manage.py migrate)→python manage.py loaddata fixtures.json - 避免在测试里用
TestCase.setUpTestData创建实例后,又在另一个 test 方法里直接查 DB——GORM/SQLAlchemy 的 session 缓存可能导致字段名变更后仍返回旧结构字段 - 团队共用的 fixture 数据文件(
fixtures.json)如果含已删除字段,加载时会静默失败,得配合--traceback参数跑测试才能看到KeyError










