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

如何在Django REST Framework中通过嵌套序列化器实现创建用户配置文件时自动创建用户?(解决TypeError报错)

问题分析

你遇到的TypeError: User() got an unexpected keyword argument 'user'主要有两个核心原因:

  1. ProfileAdmin模型错误继承User:你的ProfileAdmin同时继承了User和models.Model,这会导致Django在创建ProfileAdmin时,错误地将user参数传递给User的构造函数,但User模型并没有这个字段。
  2. 序列化器create方法逻辑顺序错误:你先创建了ProfileAdmin对象,再创建User对象,但ProfileAdmin依赖User的OneToOne关联,顺序应该反过来,并且没有正确关联两者。
分步解决方案

1. 修复ProfileAdmin模型定义

打开models.py,修改ProfileAdmin的继承关系,移除对User的继承——它只需要作为User的扩展信息存在,通过OneToOneField关联即可:

# 替换原来的ProfileAdmin定义
class ProfileAdmin(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    email = models.EmailField(verbose_name="email", max_length=85, unique=True)
    aliasMailID = models.EmailField(verbose_name="aliasMailID", max_length=85, unique=True, blank=False)
    address = models.TextField()
    MSteamsID = models.EmailField(verbose_name="MSteamsID", max_length=85, unique=True, blank=False)
    telNum = PhoneNumberField(null=False, blank=False, unique=True)

同时,删除User模型中重复定义的password字段——因为AbstractBaseUser已经包含了这个字段,重复定义会导致字段冲突:

class User(AbstractBaseUser, PermissionsMixin):
    # 移除下面这行重复定义的密码字段
    # password = models.CharField(_('password'), max_length=128)
    # ... 其他字段保持不变

2. 修正序列化器的create和update方法

打开serializers.py,调整UserProfileSerializer的逻辑:先创建User对象(用自定义管理器的方法处理密码哈希),再关联创建ProfileAdmin,同时完善更新逻辑:

class UserProfileSerializer(serializers.ModelSerializer):
    user_account = UserSerializer(many=False)

    class Meta:
        model = ProfileAdmin
        fields = ['email', 'first_name', 'last_name', 'address', 'telNum', 'aliasMailID', 'MSteamsID', 'user_account']

    def create(self, validated_data):
        account_data = validated_data.pop('user_account')
        # 使用自定义管理器的create_user方法创建User,自动处理密码哈希
        user = User.objects.create_user(
            username=account_data['username'],
            password=account_data['password'],
            user_type=account_data['user_type']
        )
        # 创建ProfileAdmin并关联刚创建的User
        profile = ProfileAdmin.objects.create(user=user, **validated_data)
        return profile

    def update(self, instance, validated_data):
        account_data = validated_data.pop('user_account')
        user_account = instance.user
        
        # 更新ProfileAdmin字段
        instance.email = validated_data.get('email', instance.email)
        instance.first_name = validated_data.get('first_name', instance.first_name)
        instance.last_name = validated_data.get('last_name', instance.last_name)
        instance.address = validated_data.get('address', instance.address)
        instance.telNum = validated_data.get('telNum', instance.telNum)
        instance.aliasMailID = validated_data.get('aliasMailID', instance.aliasMailID)
        instance.MSteamsID = validated_data.get('MSteamsID', instance.MSteamsID)
        instance.save()
        
        # 更新User字段
        user_account.username = account_data.get('username', user_account.username)
        user_account.user_type = account_data.get('user_type', user_account.user_type)
        # 单独处理密码更新,确保哈希加密
        if 'password' in account_data:
            user_account.set_password(account_data['password'])
        user_account.save()
        
        return instance

3. 扩展支持多角色Profile(可选)

如果你需要支持Instructor和Student的Profile,可以参考ProfileAdmin创建对应的ProfileInstructor和ProfileStudent模型,然后编写一个动态序列化器,根据user_type自动匹配对应的Profile序列化器:

class DynamicProfileSerializer(serializers.Serializer):
    def to_representation(self, instance):
        user_type = instance.user.user_type
        if user_type == 'ADMIN':
            return UserProfileSerializer(instance).data
        elif user_type == 'INSTRUCTOR':
            return InstructorProfileSerializer(instance).data
        elif user_type == 'STUDENT':
            return StudentProfileSerializer(instance).data
        return super().to_representation(instance)

4. 数据库迁移

修改模型后,执行以下命令更新数据库结构:

python manage.py makemigrations
python manage.py migrate
测试验证

重新运行服务后,访问http://localhost:8000/api/users/,提交如下格式的JSON请求即可正常创建关联的User和ProfileAdmin:

{
    "email": "admin@example.com",
    "first_name": "John",
    "last_name": "Doe",
    "address": "123 Street",
    "telNum": "+1234567890",
    "aliasMailID": "admin_alias@example.com",
    "MSteamsID": "admin_teams@example.com",
    "user_account": {
        "username": "admin_user",
        "password": "admin123",
        "user_type": "ADMIN"
    }
}

内容的提问来源于stack exchange,提问作者Ravi Trivedi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 17:02:45