Django DRF:使序列化程序字段值等于另一个值

Django DRF:使序列化程序字段值等于另一个值,django,django-rest-framework,Django,Django Rest Framework,我正在创建一个端点来重置密码,并创建了序列化程序、视图,我正在使用django.contrib.auth.forms获取数据并向用户发送电子邮件。 表单要求键入两次新密码,但我想要的是只写入一次,并使new\u password2的值等于new\u password1。例如,我想更改Swagger上的密码,但键入两次没有意义,因为它是一个普通的CharField而不是PasswordField 这是serializers.pyResetPasswordConfirm类 class ResetPa

我正在创建一个端点来重置密码,并创建了序列化程序、视图,我正在使用django.contrib.auth.forms获取数据并向用户发送电子邮件。 表单要求键入两次新密码,但我想要的是只写入一次,并使
new\u password2
的值等于
new\u password1
。例如,我想更改Swagger上的密码,但键入两次没有意义,因为它是一个普通的CharField而不是PasswordField

这是
serializers.py
ResetPasswordConfirm类

class ResetPasswordConfirmSerializer(serializers.Serializer):

    new_password1 = serializers.CharField(max_length=128)
    new_password2 = serializers.CharField(max_length=128)
    uid = serializers.CharField()
    token = serializers.CharField()
    set_password_form_class = SetPasswordForm

def __init__(self, *args, **kwargs):
    super(ResetPasswordConfirmSerializer, self).__init__(*args, **kwargs)
    self.set_password_form = None

def validate(self, value, *args, **kwargs):
    try:
        uid = force_text(uid_decoder(value['uid']))
        user = User.objects.get(pk=uid)
    except (TypeError, ValueError, OverflowError, User.DoesNotExist):
        raise ValidationError({
            'uid': ['Invalid value']
        })

    self.set_password_form = self.set_password_form_class(user=user, data=value)
    if not self.set_password_form.is_valid():
        raise serializers.ValidationError(self.set_password_form.errors)
    if not default_token_generator.check_token(user, value['token']):
        raise ValidationError({
            'token': ['Invalid value']
        })
    return value

def save(self, **kwargs):
    return self.set_password_form.save()
以及API视图

class ResetPasswordConfirmAPIView(GenericAPIView):
    serializer_class = ResetPasswordConfirmSerializer
    permission_classes = (AllowAny,)

@method_decorator(csrf_protect)
def dispatch(self, *args, **kwargs):
    return super(ResetPasswordConfirmAPIView, self).dispatch(*args, **kwargs)

def post(self, request):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    serializer.save()
    return Response({
        'detail': _("Password has been reset"),
    }, status=status.HTTP_200_OK)

我尝试了不同的方法来创建新密码2,但是我遇到了错误。有什么建议吗?

您只能在序列化程序中保留
新密码1
,并更新发送到
验证方法中表单的数据:

class ResetPasswordConfirmSerializer(serializers.Serializer):

    new_password1 = serializers.CharField(max_length=128)
    uid = serializers.CharField()
    token = serializers.CharField()
    set_password_form_class = SetPasswordForm

    def __init__(self, *args, **kwargs):
        super(ResetPasswordConfirmSerializer, self).__init__(*args, **kwargs)
        self.set_password_form = None

    def validate(self, value, *args, **kwargs):
        try:
            uid = force_text(uid_decoder(value['uid']))
            user = User.objects.get(pk=uid)
        except (TypeError, ValueError, OverflowError, User.DoesNotExist):
            raise ValidationError({
                'uid': ['Invalid value']
            })

        new_value = value.copy()
        new_value['new_password2'] = value['new_password1'] 

        self.set_password_form = self.set_password_form_class(user=user, data=new_value)
        if not self.set_password_form.is_valid():
            raise serializers.ValidationError(self.set_password_form.errors)
        if not default_token_generator.check_token(user, value['token']):
            raise ValidationError({
                'token': ['Invalid value']
            })
        return value

    def save(self, **kwargs):
        return self.set_password_form.save()
但我认为,不使用表单也有可能而且更清楚,您可以使用django的函数来验证密码。我没有测试它,但您可以尝试以下内容:

from django.contrib.auth.password_validation import validate_password

class ResetPasswordConfirmSerializer(serializers.Serializer):
    new_password1 = serializers.CharField(max_length=128)
    uid = serializers.CharField()
    token = serializers.CharField()

    def validate(self, value, *args, **kwargs):
        try:
            uid = force_text(uid_decoder(value['uid']))
            user = User.objects.get(pk=uid)
        except (TypeError, ValueError, OverflowError, User.DoesNotExist):
            raise ValidationError({
                'uid': ['Invalid value']
            })

        if not default_token_generator.check_token(user, value['token']):
            raise ValidationError({
                'token': ['Invalid value']
            })
        validate_password(password=value['new_password1'], user=user) 
        return value

    def save(self, **kwargs):
        user = User.objects.get(pk=self.validated_data['uid'])  
        user.set_password(self.validated_data['new_password1'])
        user.save()
        return user

完美的谢谢。没有考虑复制值并使用新的dict传递到表单。@XhensB不客气!我已经用无格式的方法更新了我的答案。你也可以检查一下。非常有用的答案!:)@XhensB经过一些新的编辑后,我希望它更清晰:)肯定:)现在我正在考虑处理序列化程序中的所有内容