如何在现有模型上更改pk字段?

时间:2019-11-05 17:27:08

标签: django django-models

我有一个用户模型,其中有一个AutoField作为pk字段。现在,我想将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)然后我创建了空迁移并填充了新的uuid

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)在此步骤之前,一切正常。然后我尝试用新的ID填充我的相关模型

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')

这意味着用户应用程序没有令牌模型。为了解决这个问题,我将每个模块的最后一次迁移添加到依赖项中。仍然有同样的错误。

什么是使迁移识别其他模块模型的正确方法?

0 个答案:

没有答案