Как правильно изменить пароль пользовательского пользователя?
Я работаю над своим приложением Django (DRF). Есть CustomUser
модель
class CustomAccountManager(BaseUserManager):
def create_superuser(self, email, user_name, password, **other_fields):
...
def create_user(self, email, user_name, password, **other_fields):
if not email:
raise ValueError(_('You must provide an email address'))
email = self.normalize_email(email)
user = self.model(email=email, user_name=user_name, **other_fields)
user.set_password(password)
user.save()
return user
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
user_name = models.CharField(max_length=150, unique=True) # Full name
phone_number = models.CharField(max_length=20, unique=True)
...
Я создал пользовательский способ смены пароля. Я посылаю current_password, new_password_verify и new_password_verify в параметре body.
Каким образом правильно реализовать смену пароля в Django?
class CustomUserViewSet(viewsets.ModelViewSet):
def update(self, request: Request, *args, **kwargs):
instance: CustomUser = self.get_object()
serializer = self.get_serializer(
instance, data=request.data, partial=True
)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, "_prefetched_objects_cache", None):
instance._prefetched_objects_cache = {}
return Response({
"is_password_updated": self.update_password(request, instance), # <-------UPDATE
"result": serializer.data
})
def update_password(self, request, instance):
"""update password if 'new_password_verify' and 'new_password' are in request"""
if "current_password" in request.data and instance.check_password(request.data["current_password"]) and \
"new_password" in request.data and "new_password_verify" in request.data and \
request.data["new_password"] == request.data["new_password_verify"]:
instance.set_password(request.data["new_password"])
instance.save()
return True
return False
Я думаю, что вы можете извлечь логику проверки из представления, чтобы сделать его более модульным, определив сериализатор.
class ChangePasswordSerializer(serializers.Serializer):
current_password = serializers.CharField(trim_whitespace = False, validators=[validate_password]),
new_password = serializers.CharField(trim_whitespace = False, validators=[validate_password])
new_password_verify = serializers.CharField(trim_whitespace = False)
def validate(self, attrs):
if attrs.get('new_password') != attrs.get('new_password_verify'):
serializers.ValidationError('Password and confirm password do not match')
return attrs
def validate_password(value):
# you can set your own validating logic here if you want to
# for example, like validations for length or regex
pass
Конечно, вам не нужно загружать new_password_verify
данные, а проверять эту часть во фронтенде, тогда поле new_password_verify
и метод validate
не нужны и код будет проще.
class CustomUserViewSet(viewsets.ModelViewSet):
def update(self, request: Request, *args, **kwargs):
...
return Response({
"is_password_updated": self.update_password(request, instance)
"result": serializer.data
})
def update_password(self, request, instance):
serializer = ChangePasswordSerializer(data = request.data)
if serializer.is_valid():
input_data = serializer.validated_data
cur_password = input_data.get('current_password')
new_password = input_data.get('new_password')
if instance.check_password(cur_password):
instance.set_password(new_password)
instance.save()
return True
return False