我正在创建一个端点来重置密码,并创建了序列化程序,视图,我使用django.contrib.auth.forms来获取数据并向用户发送电子邮件。
表单需要输入两次新密码,但我想要的是,只需编写一次,并使new_password2
的值等于new_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)
我尝试了不同的方式来new_password2
== new_password1
,但我收到错误。有什么建议吗?
答案 0 :(得分:1)
您只能在序列化程序中保留new_password1
并更新您在validate
方法内发送的数据:
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的validate_password
函数来验证密码。我没有测试它,但你可以尝试这样的事情:
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