Issue
I'm testing for multiple validation errors to be raised in(UserRegistrationSerializer)
.
Yet DRF only returns the first error that is raised:
{'username': [ErrorDetail(string='Choose a different username', code='invalid')]}
I'm expecting: {'username': [ErrorDetail(string='Choose a different username', code='invalid')], 'password2': [ErrorDetail(string='Password confirmation failed', code='invalid')]
How can multiple errors be accounted for once a serializer is validated as in the documentation example?
https://www.django-rest-framework.org/api-guide/serializers/#validation
class TestRegisterationSerializer__002(TestCase):
'''Verify that the registeration process fails with respect
to selecting an unavailable username and password confirmation'''
@classmethod
def setUpTestData(cls):
User.objects.create_user(username="Python")
cls.data = {
'username': "Python",
'password': "#secret#",
'password2': "Secret"
}
cls.error_messages = [
"Choose a different username", "Password confirmation failed"
]
cls.serializer = UserRegisterationSerializer(data=cls.data)
def test_user_registeration_invalid_confirmation(self):
self.serializer.is_valid()
print(self.serializer.errors)
import re
from django.contrib.auth.models import User
from rest_framework import serializers
class UsernameSerializer(serializers.ModelSerializer):
username = serializers.SlugField(min_length=4, max_length=12)
def validate_username(self, value):
try:
self.Meta.model.objects.get(username__iexact=value)
except self.Meta.model.DoesNotExist:
return value
raise serializers.ValidationError("Choose a different username")
class Meta:
fields = ['username', ]
model = User
class LoginSerializer(UsernameSerializer):
password = serializers.RegexField(
r"[0-9A-Za-z]+", min_length=5, max_length=8
)
def validate(self, data):
username, password = [
input.lower() for input in [data['username'], data['password']]
]
if all(password[i] == password[i + 1] for i in range(len(password) - 1)) or username == password:
raise serializers.ValidationError({
'password': "Invalid password"
})
return data
class Meta:
fields = ['username', 'password', ]
model = User
class UserRegistrationSerializer(LoginSerializer):
password2 = serializers.RegexField(
r"[0-9A-Za-z]+", min_length=5, max_length=8, write_only=True
)
def validate(self, data):
data = super().validate(data)
if data['password'] != data['password2']:
raise serializers.ValidationError({"password2": "Password confirmation failed"})
return data
class Meta:
model = User
fields = ['username', 'password', 'password2']
Solution
Please remove the customizations of validate method in UsernameSerializer and LoginSerializer and place this method inside UserRegistrationSerializer
from rest_framework.exceptions import ValidationError
def validate(self, data):
errors = []
data = super().validate(data)
username = data.get("username")
if self.Meta.model.objects.filter(username__iexact=username).exists():
errors.append({"username":"Choose a different username"})
username, password = [
input.lower() for input in [data['username'], data['password']]
]
if all(password[i] == password[i + 1] for i in range(len(password) - 1)) or username == password:
errors.append({
'password': "Invalid password"
})
if data['password'] != data['password2']:
errors.append({"password2": "Password confirmation failed"})
if errors:
raise serializers.ValidationError(errors)
return data
Answered By - Krishna Singhal
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.