Django数据迁移失败,除非单独运行

Django data migration fails unless it's run separately

我已经 运行 参与过几次,但无法弄清楚为什么会这样。当我 运行 迁移全部通过 ./manage.py migrate 时,最后一次迁移(数据迁移)失败。解决方案是 运行 在其他迁移完成后自行进行数据迁移。我怎样才能 运行 它们全部自动没有错误?

我有一系列的迁移:

  1. fulfillment/0001.py
  2. order/0041.py(依赖:fulfillment/0001.py)
  3. order/0042.py
  4. order/0043.py

我遵循了这个 RealPython article to move a model to a new app ,它工作得很好并且包含在迁移 #1 到 #3 中。迁移 #3 还添加了一个 GenericForeignKey 字段。迁移 #4 是一个数据迁移,它只是从现有的 ForeignKey 字段填充 GenericForeignKey 字段。

from django.db import migrations, models

def copy_to_generic_fk(apps, schema_editor):
    ContentType = apps.get_model('contenttypes.ContentType')
    Order = apps.get_model('order.Order')
    pickup_point_type = ContentType.objects.get(
        app_label='fulfillment',
        model='pickuppoint'
    )
    Order.objects.filter(pickup_point__isnull=False).update(
        content_type=pickup_point_type,
        object_id=models.F('pickup_point_id')
    )

class Migration(migrations.Migration):

    dependencies = [
        ('order', '0042'),
    ]

    operations = [
        migrations.RunPython(copy_to_generic_fk, reverse_code=migrations.RunPython.noop)
    ]

运行 序列在一起我得到一个错误:

fake.DoesNotExist: ContentType matching query does not exist.

如果我 运行 迁移到 #3 然后 运行 #4 本身一切正常。我怎样才能让它们按顺序到达 运行 而没有错误?

有两件事可能会解决问题,首先查看 run_before https://docs.djangoproject.com/en/3.1/howto/writing-migrations/#controlling-the-order-of-migrations 如果您将它添加到 fulfillment #1,并确保它在订单 #4 之前运行,它应该可以解决问题。

您可以做的另一件事是将您的数据迁移移动到 fulfillment #2,这样您就可以确定所有订单都已完成并且 fulfillment #1 也已完成。

不是通过 .get() 获取 ContentType,而是必须通过 apps 参数检索模型,然后使用 get_for_model().

def copy_to_generic_fk(apps, schema_editor):
    ContentType = apps.get_model('contenttypes', 'ContentType')
    PickupPoint = apps.get_model('fulfillment', 'pickuppoint')
    pickup_point_type = ContentType.objects.get_for_model(PickupPoint)
    ...