Миграция данных Django не выполняется, если она не запускается отдельно

Я сталкивался с этим пару раз и не могу понять, почему это происходит. Когда я запускаю все миграции вместе через ./manage.py migrate, последняя миграция (миграция данных) завершается сбоем. Решение состоит в том, чтобы выполнить миграцию данных самостоятельно после завершения других миграций. Как я могу запустить их все автоматически без ошибок?

У меня есть серия миграций:

  1. выполнение/0001.py
  2. заказ/0041.py (зависимость: выполнение/0001.py)
  3. заказ/0042.py
  4. заказ/0043.py

Я следовал этой статье RealPython, чтобы переместить модель в новое приложение, которое отлично работает и покрывается миграциями с №1 по №3. Миграция №3 также добавляет поле GenericForeignKey. Миграция № 4 — это миграция данных, которая просто заполняет поле GenericForeignKey из существующего поля ForeignKey.

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 не существует.

Если я запускаю миграцию на № 3, а затем запускаю № 4, все работает правильно. Как я могу заставить их работать последовательно без ошибок?


person bdoubleu    schedule 14.09.2020    source источник


Ответы (2)


Есть две вещи, которые могут решить проблему: сначала загляните в run_before https://docs.djangoproject.com/en/3.1/howto/writing-migrations/#controlling-the-order-of-migrations, если вы добавите его в выполнение №1, и убедитесь, что он работает до заказов № 4, это должно решить проблему.

Еще одна вещь, которую вы можете сделать, — это перенести миграцию данных на выполнение № 2, чтобы вы точно знали, что все заказы выполнены, и выполнение № 1 также завершено.

person camara90100    schedule 14.09.2020
comment
Спасибо за ваш комментарий. На самом деле они выполняются в правильном порядке. Это похоже на то, что предыдущие изменения миграции не фиксируются, поэтому при попытке получить объект ContentType он говорит, что модель pickuppoint не существует в приложении fulfillment; на самом деле он все еще доступен в приложении order, несмотря на перемещение, происходящее в #1 и #2. - person bdoubleu; 14.09.2020

Вместо того, чтобы получать от ContentType до .get(), вы должны получить модель через аргумент 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)
    ...
person bdoubleu    schedule 15.09.2020