Home > Net >  How are all serializer errors returned in DRF at once?
How are all serializer errors returned in DRF at once?

Time:11-30

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']


CodePudding user response:

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
  • Related