Как добавить новое поле в модель после пользовательской миграции, которая получает доступ к модели перед новым полем?

У меня есть пользовательский файл миграции, который создает запись в таблице user. Первоначальный рабочий проект имеет такие миграции:

 1. 001_initial.py # creates model with some fields
 2. 002_custom_user_data.py # adds data in "user" due some middle requirement after some time.

Теперь я хочу добавить еще один столбец в эту таблицу как "config_data". Для этого я выполнил следующие шаги:

 1. python manage.py makemigrations <app-name> # creates one more migration file` 003_add_config_data_field.py
 2. python manage.py migrate # raise an error
Команда

migrate вызывает ошибку ниже.

      Applying my_user.001_initial.py... OK
      Applying my_user.002_custom_user_data.py ...Traceback (most recent call last):
  File "/home/myhome/.local/share/virtualenvs/myproject/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.UndefinedColumn: column my_user.config_data does not exist
LINE 1: ..., "my_user"."address",

Это происходит потому, что миграция 002 пытается получить доступ к таблице my_user до того, как миграция add field(003) будет перенесена в таблицу, что вызывает ошибку UndefinedColumn config_data error.

Есть идеи, как можно решить эту проблему, поскольку эти миграции должны работать как для свежей БД, так и для производственной БД, в которой до 002 мигрировали ранее.

Ниже приведена миграция для 002_custom_user_data.py

# Generated by Django 3.2.2

from django.db import migrations
from myapp.models import MyUser


def create_user(apps, schema_editor):
    user = MyUser.objects.get_or_create(id=123)
    user.address = 'demo'
    user.save()


def delete_user(apps, schema_editor):
    MyUser.objects.filter(id=123).delete()


class Migration(migrations.Migration):

    dependencies = [
        ('my_user', '001_initial'),
    ]

Спасибо.

Вам следует импортировать модель historical, а не вашу текущую модель. Django отслеживает, как выглядела модель до того, как вы запустили миграцию, вы можете получить доступ к такой модели с помощью метода apps.get_model(…) [Django-doc]:

from django.db import migrations
# No import from myapp.models!


def create_user(apps, schema_editor):
    MyUser = apps.get_model('my_user', 'MyUser')
    user = MyUser.objects.get_or_create(id=123)
    user.address = 'demo'
    user.save()


def delete_user(apps, schema_editor):
    MyUser = apps.get_model('my_user', 'MyUser')
    MyUser.objects.filter(id=123).delete()


class Migration(migrations.Migration):

    dependencies = [
        ('my_user', '001_initial'),
    ]

Модель MyUser, которую мы здесь используем, сама по себе не будет иметь все поля, которые вы определили в models.py, и поля сами по себе не будут иметь тот же тип. Таким образом, вы можете работать с моделью так, как она была в тот момент времени, и таким образом определять миграции данных . Записи будут обновлены позже, если вы, например, создадите дополнительное поле.

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