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

Django REST Framework注册接口触发RecursionError问题求助

DRF注册接口RecursionError问题排查与解决

问题描述

使用Django REST Framework开发的用户注册接口此前运行正常,近期测试时触发RecursionError: maximum recursion depth exceeded错误。

相关代码

serializers.py

class RegisterSerializer(serializers.ModelSerializer):
    password = serializers.CharField(
        write_only=True,
        max_length=68,
        min_length=8,
        error_messages={"min_length": f"Password must be longer than {MIN_LENGTH}characters"},
        required=True,
        validators=[validate_password]
    )
    password2 = serializers.CharField(
        write_only=True,
        max_length=68,
        min_length=8,
        error_messages={"min_length": f"Password must be longer than {MIN_LENGTH}characters"},
        required=True
    )

    class Meta:
        model = User
        fields = ('username','phone','password','password2')

    # 错误位置:extra_kwargs定义在Meta类外部
    extra_kwargs = {
        'password': {'write_only': True},
        'password2': {'write_only': True}
    }
    
    def validate(self,data):
        if data["password"]!=data["password2"]:
            raise serializers.ValidationError("password does not match!")
        return data

    def create(self,validated_data):
        # 不规范:使用self.validated_data而非传入的参数
        user = User.objects.create(
            phone=self.validated_data['phone'],
            username=self.validated_data['username'],
        )
        user.set_password(validated_data['password'])
        user.save()
        return user 

views.py

class RegisterViewSet(viewsets.ModelViewSet):
    http_method_names = ['post']
    '''This endpoint is made to register all user with phone number and password'''
    queryset = User.objects.all()
    serializer_class = RegisterSerializer

错误原因

  1. extra_kwargs配置位置错误:ModelSerializer的extra_kwargs必须定义在class Meta内部,当前定义在外部会导致DRF无法识别该配置,进而在序列化返回的用户对象时,无法正确应用write_only属性,触发无限递归的字段处理逻辑。
  2. create方法参数使用不规范:create方法中使用self.validated_data而非传入的validated_data参数,虽不直接引发递归,但不符合DRF序列化器的规范写法,可能引发潜在的上下文问题。

解决方法

1. 修正extra_kwargs的位置

将extra_kwargs移动到class Meta内部:

class RegisterSerializer(serializers.ModelSerializer):
    password = serializers.CharField(
        write_only=True,
        max_length=68,
        min_length=8,
        error_messages={"min_length": f"Password must be longer than {MIN_LENGTH}characters"},
        required=True,
        validators=[validate_password]
    )
    password2 = serializers.CharField(
        write_only=True,
        max_length=68,
        min_length=8,
        error_messages={"min_length": f"Password must be longer than {MIN_LENGTH}characters"},
        required=True
    )

    class Meta:
        model = User
        fields = ('username','phone','password','password2')
        # 修正:extra_kwargs移至Meta内部
        extra_kwargs = {
            'password': {'write_only': True},
            'password2': {'write_only': True}
        }
    
    # 剩余方法保持不变(后续修正create方法)

2. 规范create方法的参数使用

将self.validated_data替换为方法传入的validated_data参数:

def create(self, validated_data):
    user = User.objects.create(
        phone=validated_data['phone'],
        username=validated_data['username'],
    )
    user.set_password(validated_data['password'])
    user.save()
    return user 

3. 可选优化(避免重复配置)

由于已经在extra_kwargs中设置了write_only=True,可以移除字段显式定义中的write_only=True,减少重复配置:

password = serializers.CharField(
    max_length=68,
    min_length=8,
    error_messages={"min_length": f"Password must be longer than {MIN_LENGTH}characters"},
    required=True,
    validators=[validate_password]
)
password2 = serializers.CharField(
    max_length=68,
    min_length=8,
    error_messages={"min_length": f"Password must be longer than {MIN_LENGTH}characters"},
    required=True
)

验证

修改完成后重新测试注册接口,RecursionError应被解决,接口可正常创建用户并返回序列化后的用户数据(password字段不会出现在响应中)。

内容的提问来源于stack exchange,提问作者siaka karl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 11:24:10