如何解决django CustomUser在迁移中的Dual behavior问题?

How to solve the problem of Dual behavior of django CustomUser in migration?

我有如下数据迁移,其中我想使用 CustomUser 的 create_user 方法,获取已创建用户的实例,并使用此实例创建合作伙伴模型的实例。 值得一提的是,我有一个与 CustomUser 具有一对一关系的 Partner 模型。 我有两个选择:

# Option One:

def populate_database_create_partner(apps, schema_editor):
    Partner = apps.get_model('partners', 'Partner')

    CustomUser.objects.create_user(
        id=33,
        email='test_email@email.com',
        password='password',
        first_name='test_first_name',
        last_name="test_last_name",
        is_partner=True,
    )

    u = CustomUser.objects.get(id=33)
    partner = Partner.objects.create(user=u, )


class Migration(migrations.Migration):

    dependencies = [
        ('accounts', '0006_populate_database_createsuperuser'),
    ]

    operations = [
        migrations.RunPython(populate_database_create_partner),
    ]

在选项一中,我看到了这个错误:

ValueError: Cannot assign "<CustomUser: test_email@email.com>": "Partner.user" must be a "CustomUser" instance.

然后我测试这个:

# Option Two:

def populate_database_create_partner(apps, schema_editor):
    Partner = apps.get_model('partners', 'Partner')
    CustomUser = apps.get_model('accounts', 'CustomUser')


    CustomUser.objects.create_user(
        id=33,
        email='test_email@email.com',
        password='password',
        first_name='test_first_name',
        last_name="test_last_name",
        is_partner=True,
    )

    u = CustomUser.objects.get(id=33)
    partner = Partner.objects.create(user=u, )


class Migration(migrations.Migration):

    dependencies = [
        ('accounts', '0006_populate_database_createsuperuser'),
    ]

    operations = [
        migrations.RunPython(populate_database_create_partner),
    ]

我看到这个错误:

CustomUser.objects.create_user(
AttributeError: 'Manager' object has no attribute 'create_user'

create_user方法无效。

如果我不使用create_user方法而只使用CustomUser.objects.create(...),我将无法在这里设置密码。

Django 仅保留有关每个模型版本的有限历史信息。如记录 here 所述,它没有跟踪的事情之一是自定义模型管理器。

好消息是 there's a way 强制迁移系统使用您的自定义管理器:

You can optionally serialize managers into migrations and have them available in RunPython operations. This is done by defining a use_in_migrations attribute on the manager class.

如前所述,这仅允许您的迁移使用迁移 运行 时存在的管理器版本;因此,如果您稍后对其进行更改,则可能会中断迁移。更安全的替代方法是将相关的 create_user 代码复制到迁移本身中。