Django数据迁移分配用户报错:无法赋值User实例给Client.primary_contact
解决Django迁移中
Cannot assign "User": "Client.primary_contact" must be a "User" instance错误 问题重现
执行pytest初始化时,数据迁移抛出如下错误:
ValueError: Cannot assign "<User: redshred_default_contact>": "Client.primary_contact" must be a "User" instance.
调试时确认isinstance(default_user, User)和isinstance(default_user, get_user_model())均返回True,但外键赋值仍失败。
问题原因
Django迁移运行时使用的是历史模型版本——这些模型是从迁移依赖中动态构建的,和你直接从django.contrib.auth.models导入的当前模型类不是同一个Python对象。
你的迁移代码里,Client模型通过apps.get_model获取(符合迁移规范),但User和Group却直接用了导入的类创建实例。两者的模型类版本不匹配,导致外键字段进行类型校验时失败。
解决方案
修改迁移函数,所有模型类统一通过apps.get_model获取,确保使用同一版本的模型类:
# Generated by Django 4.2.4 on 2023-09-14 18:13 from django.db import migrations from django.conf import settings def assign_default_client(apps, schema_editor): Client = apps.get_model("apiserver_v2", "Client") # 从配置中解析用户模型的app和名称,兼容自定义用户模型 user_app, user_model = settings.AUTH_USER_MODEL.split('.') User = apps.get_model(user_app, user_model) client = Client.objects.get(slug="default-client") User.objects.update(account__client=client) def create_default_client(apps, schema_editor): # 通过apps获取用户模型 user_app, user_model = settings.AUTH_USER_MODEL.split('.') User = apps.get_model(user_app, user_model) (default_user, _) = User.objects.get_or_create(username="default_contact") default_user.save() Client = apps.get_model("apiserver_v2", "Client") client = Client.objects.create( name="Default Client", slug="default-client", primary_contact=default_user, domain="mydomain.com", ) # 通过apps获取Group模型 Group = apps.get_model('auth', 'Group') (group, _) = Group.objects.get_or_create(name="default_contact_group") client.new_user_group = group client.save() class Migration(migrations.Migration): dependencies = [ ("apiserver_v2", "0026_account"), ("authtoken", "0003_tokenproxy"), ] operations = [ migrations.RunPython(create_default_client, migrations.RunPython.noop), migrations.RunPython(assign_default_client, migrations.RunPython.noop), ]
关键注意事项
- 用户模型处理:通过
settings.AUTH_USER_MODEL拆分获取app和模型名,兼容默认auth.User和自定义用户模型场景,避免硬编码。 - 所有模型统一:迁移中永远不要直接导入模型类,必须使用
apps.get_model,否则会出现跨版本模型实例不兼容的问题。 - Group模型同步:Group同样需要通过
apps.get_model获取,保持迁移内模型类的一致性。
内容的提问来源于stack exchange,提问作者Skaman Sam
相关产品推荐
相关产品推荐

