60
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 sys
from django.core import exceptions
import django.contrib.auth.password_validation as validators
class 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)
17
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
- [Django]-Do CSRF attacks apply to API's?
- [Django]-Django-rest-framework 3.0 create or update in nested serializer
- [Django]-Celery and Django simple example
11
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
- [Django]-How to make the foreign key field optional in Django model?
- [Django]-How does Django Know the Order to Render Form Fields?
- [Django]-Using window functions in an update statement
0
At the time of creating new user(registration) then self.instance will be none, it will work when
your are resting the password, change password or updating user data with password.
But if you want to check the password should not be similar to your email or username then you need to include “SequenceMatcher”
in your validation
data = self.get_initial()
username = data.get("username")
email = data.get("email")
password = data.get("password")
max_similarity = 0.7
if SequenceMatcher(a=password.lower(), b=username.lower()).quick_ratio() > max_similarity:
raise serializers.ValidationError("The password is too similar to the username.")
if SequenceMatcher(a=password.lower(), b=email.lower()).quick_ratio() > max_similarity:
raise serializers.ValidationError("The password is too similar to the email.")
- [Django]-Change a form value before validation in Django form
- [Django]-ImproperlyConfigured: You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings
- [Django]-Adding a APIView to Django REST Framework Browsable API