У меня есть пользовательская модель, в которой в качестве поля pk используется AutoField. Теперь я хочу изменить pk на uuid, так как мне нужно использовать его в моем API. Самая большая проблема заключается в том, что проект уже запущен, и есть некоторые сторонние приложения, которые имеют отношение к модели пользователя. Например, это модель маркера DRF.
Я попытался написать несколько миграций для замены таблиц и обеспечения безопасности моих данных.
вот модель пользователя:
class User(PermissionsMixin, AbstractBaseUser):
email = models.EmailField(_("email address"), max_length=64, unique=True)
first_name = models.CharField(_("first name"), max_length=30, blank=True)
last_name = models.CharField(_("last name"), max_length=50, blank=True)
Вотмои шаги:
1) Я создал первую миграцию, добавив uuid = models.UUIDField(default=uuid4, editable=False)
2) Затем я создал пустые миграции и заполнил новые uuids
from uuid import uuid4
from django.db import migrations
def fill_ids(apps, schema_editor):
user_model = apps.get_model("users", "User")
for user in user_model.objects.all():
user.uuid = uuid4()
user.save()
class Migration(migrations.Migration):
dependencies = [
('users', '0002_user_uuid'),
]
operations = [
migrations.RunPython(fill_ids)
]
3) ПередНа этом этапе все работает хорошо. Затем я попытался заполнить соответствующие модели новыми идентификаторами
from django.db import migrations, models
from django.conf import settings
def change_model_fks(apps, schema_editor):
log_model = apps.get_model('admin', 'logentry')
token_model = apps.get_model('authtoken', 'token')
user_model = apps.get_model('users', "user")
mapping = {}
for user in user_model.objects.all():
mapping[user.id] = user.uuid # map old primary keys to new
for token in token_model.objects.all():
if token.user_id:
token.user_id = mapping[token.user_id]
token.save()
for log in log_model.objects.all():
if log.user_id:
log.user_id = mapping[log.user_id]
log.save()
class Migration(migrations.Migration):
dependencies = [
('users', '0003_auto_20191105_1601'),
('authtoken', '0002_auto_20160226_1747'),
('admin', '0003_logentry_add_action_flag_choices')
]
operations = [
migrations.AlterField(
model_name="Token",
name='user',
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name='user',
db_constraint=False)
),
migrations.AlterField(
model_name="EntryLog",
name='user',
field=models.OneToOneField(to=settings.AUTH_USER_MODEL, related_name='auth_token',
on_delete=models.CASCADE, db_constraint=False)
),
migrations.RunPython(change_model_fks, atomic=True),
migrations.AlterField(
model_name="Token",
name='user',
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name='user')
),
migrations.AlterField(
model_name="EntryLog",
name='user',
field=models.OneToOneField(to=settings.AUTH_USER_MODEL, related_name='auth_token', on_delete=models.CASCADE)
),
]
. Я перенес эти миграции с ошибкой: KeyError: ('users', 'token')
Это означает, что в приложении пользователя нет модели токенов. Чтобы это исправить, я добавил последнюю миграцию для каждого модуля в зависимости. Все еще есть та же ошибка.
Как правильно выполнить миграцию, чтобы распознавать модели из других модулей?