Переименование модели Django без нарушения существующих миграций

Я хочу переименовать модель в Django 3.2, сохранить существующие миграции и иметь возможность как перенести базу данных со старым именем таблицы, так и создать базу данных с нуля.

Я начал с переименования класса модели и всех ссылок на него в коде. Поскольку "./manage.py makemigrations" не создал миграцию автоматически, я вручную создал миграцию, которая переименовала модель:

from django.db import migrations

class Migration(migrations.Migration):

    dependencies = [
        ('market_integrations', '0003_migration'),
    ]

    operations = [
        migrations.RenameModel('OldModelName', 'NewModelname')
    ]

Моя первоначальная идея заключается в том, что я не должен обновлять существующие миграции, как я никогда не делаю этого при создании других миграций. Однако ссылки на старую модель в старых миграциях вызывают ошибку LookupError, когда я запускаю "./manage.py migrate". Я пробовал использовать как строку имени модели, так и apps.get_model(). Примеры кода миграции, которые ломаются:

operations = [
    migrations.CreateModel(
        name="OldModelName",
    ...
    )
]


operations = [
    migrations.CreateModel(
        name=apps.get_model("myapp", "OldModelName"),
    ...
    )
]

Поскольку сохранение старого имени модели в старых миграциях не сработало, я заменил старое имя модели в старых миграциях на новое имя. "./manage.py migrate" успешно запустился, включая миграцию с переименованием модели. Однако, когда я пытаюсь создать новую базу данных, миграция переименования модели не срабатывает, поскольку в новой базе данных никогда не было таблицы со старым именем

Что я должен сделать, чтобы сохранить мои миграции и чтобы они работали как в существующих, так и в новых базах данных?

Я уже проверил Стратегию миграции на Django для переименования модели и полей отношений, но не нашел там ответа на свой вопрос.

Пожалуйста, приложите полную модель (вы можете удалить неактуальные поля) и миграцию, которую вы создали в вашем первоначальном вопросе (я пока не могу прокомментировать ваше первоначальное сообщение, поэтому я должен упомянуть его в ответе).

Это важно, потому что я думаю, что есть внешние ключи, указывающие на модель, которую вы хотите переименовать. Или вы пытаетесь переименовать Foo в Bar и создать новый Foo?

Возникает ли ошибка, если вы пытаетесь запустить сервер после вашей первоначальной идеи? Ваша первоначальная идея сохранить существующие миграции нетронутыми кажется хорошей, потому что вы сможете запустить ее на всех ваших средах (локальной, dev, prod и т.д.), а подход 2 потребует ручного переименования таблиц и полей базы данных.

Возможно, я смогу расширить свой ответ после того, как вы предоставите модели и миграции.

    migrations.RenameModel(
        old_name="ModelA",
        new_name="ModelB",
    ),

    migrations.AlterField(
        model_name="myrelatedmodel",
        name="somefieldname",
        field=models.ForeignKey(
            # change the properties accordingly (best copy it over). The database may only change to="table"
            null=True,
            on_delete=django.db.models.deletion.SET_NULL,
            to="myapp.modelb",
        ),
    ),

Если это не сработало, откуда берется ошибка? Вы можете попробовать изолировать ваши миграции и модели от остального кода (например, в новом пустом проекте, подключенном к той же базе данных). Возможно, это поможет вам выяснить, является ли ошибка следствием оставшейся ссылки на OldModelName или какой-то странной ошибки. Просто как идея, чтобы не тратить время на поиски не в том месте

Старайтесь делать одно изменение и один переход за раз. Позже вы сможете их разбить. Если django не автоопределяет переименование вашей модели, это означает, что все поля, связанные с этой моделью, тоже не будут работать.

  1. Revert everything to the working state before renaming
  2. Make sure all migrations are applied
  3. Rename the model and create a migration to only rename the model. Are you able to apply it?
  4. if not, try to manually modify all related fields (one2one, foreignkey, etc)

Если это все еще не удается, создайте копию вашей модели в models.py, переименуйте скопированную модель и попробуйте использовать migrations.RunPython() в новом файле миграции, чтобы скопировать все данные из старой таблицы в новую.

Если у вас только одна заполненная база данных, вы можете обойтись заменой всех вхождений ModelA на ModelB и изменить структуру базы данных.

Желаю удачи!

Вернуться на верх