You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Django CustomUser在数据迁移中的双重行为问题?

Django数据迁移中使用CustomUser.create_user并关联一对一Partner模型的解决方案

我来帮你解决这个Django数据迁移的问题,你遇到的两个错误其实都是迁移框架的特性导致的,咱们一步步来理清楚:

错误原因分析

方案一的ValueError

你直接使用了全局的CustomUser类,但迁移过程中,apps.get_model('partners', 'Partner')获取的是历史版本的Partner模型,它和你直接导入的CustomUser不属于同一个迁移上下文,所以会出现"实例类型不匹配"的错误——Django认为你传入的CustomUser实例不是当前迁移上下文里Partner需要的那个类型。

方案二的AttributeError

通过apps.get_model获取的CustomUser是迁移框架生成的"历史模型类",它只会包含模型的基本字段和默认管理器,自定义管理器的create_user方法不会被包含进去,所以会提示管理器没有这个属性。

解决方法

方法一:手动处理密码哈希(推荐)

create_user方法的核心作用就是帮你把明文密码哈希后存储,我们可以手动用set_password方法实现同样的效果,同时全程使用迁移上下文里的模型:

def populate_database_create_partner(apps, schema_editor):
    # 从迁移上下文获取模型
    CustomUser = apps.get_model('accounts', 'CustomUser')
    Partner = apps.get_model('partners', 'Partner')
    
    # 创建用户实例(先不设置密码)
    user = CustomUser.objects.create(
        id=33,
        email='test_email@email.com',
        first_name='test_first_name',
        last_name="test_last_name",
        is_partner=True,
        # 补充你的CustomUser模型中必填的其他字段,比如is_active=True(如果默认值不是True的话)
    )
    
    # 手动设置哈希密码并保存
    user.set_password('password')
    user.save()
    
    # 创建关联的Partner实例
    Partner.objects.create(user=user)

class Migration(migrations.Migration):
    dependencies = [
        ('accounts', '0006_populate_database_createsuperuser'),
    ]
    operations = [
        migrations.RunPython(populate_database_create_partner),
    ]

方法二:调用自定义管理器的create_user方法

如果你的create_user方法有额外的逻辑(不止哈希密码),可以直接导入自定义管理器来调用,但要注意:这种方式依赖你当前的管理器代码,若后续管理器逻辑修改,旧迁移可能出问题,所以谨慎使用:

假设你的CustomUser使用了自定义管理器CustomUserManager,代码如下:

from accounts.models import CustomUserManager

def populate_database_create_partner(apps, schema_editor):
    CustomUser = apps.get_model('accounts', 'CustomUser')
    Partner = apps.get_model('partners', 'Partner')
    
    # 用自定义管理器创建用户
    user = CustomUserManager().create_user(
        id=33,
        email='test_email@email.com',
        password='password',
        first_name='test_first_name',
        last_name="test_last_name",
        is_partner=True,
    )
    
    # 创建关联的Partner
    Partner.objects.create(user=user)

class Migration(migrations.Migration):
    dependencies = [
        ('accounts', '0006_populate_database_createsuperuser'),
    ]
    operations = [
        migrations.RunPython(populate_database_create_partner),
    ]

关键注意事项

  • 迁移中必须使用apps.get_model获取模型,永远不要直接导入当前的模型类,避免模型版本不匹配的问题。
  • set_password是Django用户模型的内置方法,无论是否自定义用户模型都可以使用,它会自动处理密码的哈希逻辑,和create_user的效果一致。

内容的提问来源于stack exchange,提问作者Amin Ba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:15:47