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
错误原因
- extra_kwargs配置位置错误:
ModelSerializer的extra_kwargs必须定义在class Meta内部,当前定义在外部会导致DRF无法识别该配置,进而在序列化返回的用户对象时,无法正确应用write_only属性,触发无限递归的字段处理逻辑。 - 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
相关产品推荐
相关产品推荐

