integrate django password validators with django rest framework validate_password
Like you mentioned, when you validate the password
in validate_password
method using UserAttributeSimilarityValidator
validator, you don't have the user
object.
What I suggest that instead of doing field-level validation, you shall perform object-level validation by implementing validate
method on the serializer:
import sysfrom django.core import exceptionsimport django.contrib.auth.password_validation as validatorsclass RegisterUserSerializer(serializers.ModelSerializer): # rest of the code def validate(self, data): # here data has all the fields which have validated values # so we can create a User instance out of it user = User(**data) # get the password from the data password = data.get('password') errors = dict() try: # validate the password and catch the exception validators.validate_password(password=password, user=User) # the exception raised here is different than serializers.ValidationError except exceptions.ValidationError as e: errors['password'] = list(e.messages) if errors: raise serializers.ValidationError(errors) return super(RegisterUserSerializer, self).validate(data)
You can access the user object through self.instance
on the serializer object, even when doing field-level validation. Something like this should work:
from django.contrib.auth import password_validation def validate_password(self, value): password_validation.validate_password(value, self.instance) return value
Use Serializers! Have a validate_fieldname
method!
class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ( 'id', 'username', 'password', 'first_name', 'last_name', 'email' ) extra_kwargs = { 'password': {'write_only': True}, 'username': {'read_only': True} } def validate_password(self, value): try: validate_password(value) except ValidationError as exc: raise serializers.ValidationError(str(exc)) return value def create(self, validated_data): user = super().create(validated_data) user.set_password(validated_data['password']) user.is_active = False user.save() return user def update(self, instance, validated_data): user = super().update(instance, validated_data) if 'password' in validated_data: user.set_password(validated_data['password']) user.save() return user