You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的迁移检测机制无法正确识别外键引用的一致性,常见触发场景包括:

  1. 跨应用外键使用字符串引用("grn.GRN")时,Django解析字符串的逻辑与直接导入模型的检测逻辑存在隐性差异
  2. 关联应用(grn)的迁移也在修改相关字段,导致迁移依赖关系出现循环检测
  3. 迁移缓存或历史记录存在异常,导致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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 04:03:16