用途:在 Sentry 项目中生成或审查 Django 数据库迁移与数据迁移,处理新增/删除列或表、加索引、改名等场景。
主要能力与用法:
- 生成迁移:sentry django makemigrations;指定应用 sentry django makemigrations <app_name>;空迁移用于数据迁移 sentry django makemigrations <app_name> --empty。
- 生成后需审查正确性,用 sentry django sqlmigrate <app_name> <migration_name> 验证 SQL,本地用 sentry django migrate <app_name> 应用,以触发安全检。
- 编辑生成迁移时保留自动生成的 is_post_deployment 注释块。
- 测试:不要为 Django ORM 标准行为写测试;数据回填/转换迁移必须测试。使用 sentry.testutils.cases 的 TestMigrations,设置 app、migrate_from、migrate_to,在 setup_before_migration(self, apps) 中用 apps.get_model 播种,只写一个 test_* 方法;本地运行需 --migrations 与 --reuse-db,首次配合 --create-db。
- 加列:默认值用 db_default=<value>;可空用 null=True;非空必须有 db_default。大表加索引设置 is_post_deployment = True。
- 删列:分两个迁移、两个 PR,phase 2 堆叠在 phase 1 上并等其部署;phase 1 先改字段再移除并替换为 SafeRemoveField(..., deletion_action=DeletionAction.MOVE_TO_PENDING)。
- 删模型:先检查入站 FK;phase 1 给外发 FK 加 db_constraint=False,移除模型并替换为 SafeDeleteModel(..., deletion_action=DeletionAction.MOVE_TO_PENDING),并在 src/sentry/db/router.py(或 getsentry/db/router.py)的 historical_silo_assignments 中加入该表;phase 2 再执行 DELETE,且保留该条目。
- 改名:不要在 Postgres 中重命名,用 db_column 或 Meta.db_table 保留旧名。
- 冲突处理:migrations_lockfile.txt 冲突时执行 bin/update-migration <migration_name>。
限制与注意:apps.get_model 返回的历史模型没有自定义 save(),信号接收方不按实时模型触发,需显式执行必要副作用;删列与删模型必须分两阶段合并部署,否则会在旧代码运行时丢数据。