Django每次执行makemigrations重复生成迁移文件的问题
Django迁移重复生成问题
问题背景
我的应用中有如下模型:
class PutAwayProductsPosition(models.Model): products = models.ForeignKey(Product, on_delete=models.CASCADE) put_position = models.CharField(max_length=50, default=0) is_put = models.BooleanField(default=False) class PutAway(models.Model): warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE) grn = models.ForeignKey("grn.GRN", on_delete=models.CASCADE) employee_assigned = models.ForeignKey(Employee, on_delete=models.CASCADE) putaway_id = models.IntegerField(default=0) products_position = models.ManyToManyField(PutAwayProductsPosition) completely_executed = models.BooleanField(default=False) partially_executed = models.BooleanField(default=False) created = models.DateTimeField(auto_now_add=True) scheduled_datetime = models.DateTimeField(auto_now_add=True) owner = models.ForeignKey(User, on_delete=models.CASCADE)
每次执行makemigrations时,都会自动生成如下迁移文件,即使模型没有任何修改:
class Migration(migrations.Migration): dependencies = [ ('grn', '0068_auto_20230411_0703'), ('putpick', '0033_auto_20230410_0810'), ] operations = [ migrations.AlterField( model_name='putaway', name='grn', field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='grn.GRN'), ), ]
我尝试使用--fake迁移解决,但问题依旧,操作过程及输出如下:
(venv) rahulsharma@Rahuls-MacBook-Air Trakkia-Backend % python manage.py migrate --fake putpick 0034_auto_20230411_0703 Operations to perform: Target specific migration: 0034_auto_20230411_0703, from putpick Running migrations: No migrations to apply. Your models have changes that are not yet reflected in a migration, and so won't be applied. Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them. (venv) rahulsharma@Rahuls-MacBook-Air Trakkia-Backend % python manage.py makemigrations Migrations for 'grn': grn/migrations/0069_auto_20230411_0828.py - Alter field grn on grntempscans Migrations for 'putpick': putpick/migrations/0035_auto_20230411_0828.py - Alter field grn on putaway (venv) rahulsharma@Rahuls-MacBook-Air Trakkia-Backend % python manage.py migrate Operations to perform: Apply all migrations: all apps name Running migrations: Applying grn.0069_auto_20230411_0828... OK Applying putpick.0035_auto_20230411_0828... OK
现在再次运行makemigrations,仍会重复生成这两个迁移文件。
问题原因
这种重复生成迁移的核心原因是Django的迁移检测机制无法正确识别外键引用的一致性,常见触发场景包括:
- 跨应用外键使用字符串引用(
"grn.GRN")时,Django解析字符串的逻辑与直接导入模型的检测逻辑存在隐性差异 - 关联应用(
grn)的迁移也在修改相关字段,导致迁移依赖关系出现循环检测 - 迁移缓存或历史记录存在异常,导致Django误判模型与数据库 schema 不一致
解决方法
1. 统一外键引用方式(优先推荐)
将模型中的字符串引用改为直接导入的方式,避免字符串解析带来的检测偏差:
# 先从grn应用导入GRN模型 from grn.models import GRN class PutAway(models.Model): warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE) # 替换字符串引用为直接引用模型类 grn = models.ForeignKey(GRN, on_delete=models.CASCADE) employee_assigned = models.ForeignKey(Employee, on_delete=models.CASCADE) # 其余字段保持不变 putaway_id = models.IntegerField(default=0) products_position = models.ManyToManyField(PutAwayProductsPosition) completely_executed = models.BooleanField(default=False) partially_executed = models.BooleanField(default=False) created = models.DateTimeField(auto_now_add=True) scheduled_datetime = models.DateTimeField(auto_now_add=True) owner = models.ForeignKey(User, on_delete=models.CASCADE)
2. 清理重复迁移并重新同步
- 删除
putpick和grn应用下最近生成的重复迁移文件(比如0034_xxx、0035_xxx、0069_xxx这类重复的AlterField迁移) - 运行命令清理迁移缓存并标记现有迁移已应用:
python manage.py migrate --fake-initial - 重新生成迁移并应用:
python manage.py makemigrations python manage.py migrate
3. 检查关联应用的迁移稳定性
查看grn应用的0069_auto_20230411_0828.py迁移文件,确认它修改的grntempscans模型的grn字段是否会影响GRN模型的schema状态。如果grn应用存在未完成的模型变更,先完成并稳定grn的迁移,再处理putpick的问题。
4. 重置迁移(仅开发环境使用)
如果以上方法都无效,且处于开发环境(生产环境绝对禁止),可以重置迁移历史:
- 删除
putpick和grn应用的migrations目录中除__init__.py外的所有文件 - 标记迁移历史为初始状态:
python manage.py migrate --fake putpick zero python manage.py migrate --fake grn zero - 重新生成并应用迁移:
python manage.py makemigrations grn putpick python manage.py migrate
内容的提问来源于stack exchange,提问作者Rahul Sharma
相关产品推荐
相关产品推荐

