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

Django Rest Framework中创建关联Profile的用户模型时的属性错误修复

问题描述

我想在Serializer的create方法中创建关联Profile的User实例,预期接收name、email和password三个输入字段:

  • email和password用于创建User实例
  • name和User实例用于创建Profile实例

我在UserRegisterSerializer中指定模型为自定义User模型,并额外定义了User模型没有的name字段。在create方法中,我从验证数据中弹出name,用email和password创建User,再用该User和name创建Profile。

但测试创建用户时触发以下错误:

AttributeError at /api/users/register/
Got AttributeError when attempting to get a value for field name on serializer UserRegisterSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the Users instance.
The original exception text was: 'Users' object has no attribute 'name'.

我困惑的是,我并没有主动去获取name字段的值,请问该如何修复?

相关代码

Views.py

class UserRegisterAPIView(CreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserRegisterSerializer

Models.py

  • Users:自定义用户模型,包含id、email、password等字段
  • Profiles:与Users为一对一关联,包含user、name等字段

Serializers.py

User = get_user_model() 

class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profiles
        fields = '__all__'


class UserRegisterSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('name', 'email', 'password')
        
    name = serializers.CharField(max_length=255, required=True)
    
    email = serializers.EmailField(
        required=True,
        validators=[UniqueValidator(queryset=User.objects.all())],
        )
    password = serializers.CharField(
        write_only=True,
        required=True,
        style={'input_type': 'password'},
        validators=[validate_password],
        )

    def create(self, validated_data):
        name = validated_data.pop('name')
        
        # 创建用户
        user = User.objects.create_user(
            validated_data['email'],
            )
        
        # 设置密码并保存
        user.set_password(validated_data['password'])
        user.save()
        
        # 创建关联的Profile
        profile = Profiles.objects.create(
            user=user,
            name=name
            )
        profile.save()

        return user
问题原因

错误的核心原因是:

  1. UserRegisterSerializer继承自ModelSerializer,且在Meta.fields中包含了name字段
  2. 当create方法返回user实例后,Serializer会自动序列化这个实例生成响应数据
  3. 序列化过程中,Serializer会尝试从user实例中读取name字段的值,但你的Users模型并没有这个字段,因此触发AttributeError
修复方案

方案一:给name字段添加write_only=True

这是最直接的解决方法,告诉Serializername字段只用于接收输入,不参与返回结果的序列化:

name = serializers.CharField(max_length=255, required=True, write_only=True)

方案二:优化create_user调用(可选)

你的create_user调用可以简化,因为create_user方法本身支持直接传入密码并自动哈希,不需要额外调用set_password:

def create(self, validated_data):
    name = validated_data.pop('name')
    # 直接用关键字参数传递email和password,create_user自动处理密码哈希
    user = User.objects.create_user(
        email=validated_data['email'],
        password=validated_data['password']
    )
    # 创建Profile(无需单独调用save(),create方法会自动保存)
    Profiles.objects.create(user=user, name=name)
    return user

方案三:返回包含Profile的序列化数据(可选)

如果你希望返回的响应中包含Profile信息,可以添加嵌套Serializer并刷新用户实例:

class UserRegisterSerializer(serializers.ModelSerializer):
    name = serializers.CharField(max_length=255, required=True, write_only=True)
    profile = ProfileSerializer(read_only=True)  # 添加嵌套的ProfileSerializer

    class Meta:
        model = User
        fields = ('name', 'email', 'password', 'profile')
    
    # ... 其他字段定义 ...

    def create(self, validated_data):
        name = validated_data.pop('name')
        user = User.objects.create_user(**validated_data)
        Profiles.objects.create(user=user, name=name)
        # 刷新user实例,确保关联的profile被加载
        user.refresh_from_db()
        return user

内容的提问来源于stack exchange,提问作者Mark Han

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 18:22:50