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

Django REST Framework使用Serializer创建User及关联ExtendUser数据

实现方案

要在注册接口同时创建User主表和关联ExtendUser扩展表数据,不需要拆分两个序列化器调用,直接改造UserSerializer嵌套处理扩展字段即可,具体修改步骤如下:

1. 改造serializers.py

在UserSerializer中新增ExtendUser对应的写入字段,调整save方法逻辑,创建主表用户后同步创建关联扩展表记录,改造后代码如下:

class UserSerializer(serializers.ModelSerializer):
    password2 = serializers.CharField(write_only=True, style={'input_type':'password'})
    # 新增扩展表对应字段,标记为只写,仅用于入参校验写入
    address = serializers.CharField(write_only=True, max_length=300)
    phone = serializers.CharField(write_only=True, max_length=16)
    picture = serializers.ImageField(write_only=True, required=False, default="default.webp")

    class Meta:
        model = User
        # 将扩展字段加入字段列表
        fields = ['email', 'first_name', 'password', 'password2', 'address', 'phone', 'picture']
        extra_kwargs = {'password' : {'write_only':True,}}

        
    def save(self):
        password = self.validated_data['password']
        password2 = self.validated_data['password2']
        # 原有密码、邮箱校验逻辑
        if len(password) < 8:
             raise serializers.ValidationError({'error':'密码长度需为8-16位,且包含数字和字母/特殊字符'})
        if password != password2:
            raise serializers.ValidationError({'Password':'两次输入的密码不一致'})
        email = self.validated_data['email']
        if User.objects.filter(email=email).exists():
            raise serializers.ValidationError({'E-mail': f"邮箱{email}已被注册,请更换邮箱"})

        # 创建User主表记录
        user = User.objects.create_user(
            username=email, 
            email=email, 
            password=password, 
            first_name=self.validated_data['first_name']
        )
        # 同步创建关联ExtendUser扩展表记录
        ExtendUser.objects.create(
            user=user,
            address=self.validated_data['address'],
            phone=self.validated_data['phone'],
            picture=self.validated_data.get('picture', "default.webp")
        )
        return user


class ExtendUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = ExtendUser
        fields = '__all__'

原有的ExtendUserSerializer可以保留,供其他查询、更新扩展信息的接口使用,注册场景不需要单独调用。

2. 修复views.py的逻辑错误

原代码中生成JWT令牌的逻辑存在bug:RefreshToken.for_user()需要传入User模型实例,而非序列化器实例,需要先接收save()方法返回的已创建用户对象再生成令牌,修改后代码如下:

class UserRegistration(APIView):

    def post(self, request):
        serializer = UserSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 接收save返回的已创建用户实例
        created_user = serializer.save()
        # 传入用户实例生成令牌
        refreshToken = RefreshToken.for_user(created_user)
        context = {
            'access': str(refreshToken.access_token),
            'refresh': str(refreshToken)
        }
        return Response(context, status=status.HTTP_201_CREATED)

3. 接口调用说明

注册接口请求时直接将扩展字段和基础用户字段一同传入即可,因为包含图片上传字段,请求需使用multipart/form-data格式,必填参数包括:

  • email:注册邮箱
  • first_name:用户名称
  • password:登录密码
  • password2:确认密码
  • address:用户地址
  • phone:手机号
  • picture:用户头像(可选,不传则使用默认头像default.webp)

如果需要接口返回用户信息时同步带出ExtendUser的扩展字段,只需要去掉对应扩展字段的write_only=True配置,或者嵌套ExtendUserSerializer做读场景的字段映射即可,当前配置已完全满足注册时同时创建两条关联数据的需求。

内容的提问来源于stack exchange,提问作者Partho Debnath

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 17:45:38