es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo se devuelven todos los errores del serializador de DRF de una vez?

Estoy probando la elevación de múltiples errores de validación en (UserRegistrationSerializer). Sin embargo, DRF solo devuelve el primer error que se produce: {‘username’: [ErrorDetail(string=’Choose a different username’, code=’invalid’)]}

Espero: {‘username’: [ErrorDetail(string=’Choose a different username’, code=’invalid’)], ‘password2′: [ErrorDetail(string=’Password confirmation failed’, code=’invalid’)]}

¿Cómo se pueden tener en cuenta múltiples errores una vez que se ha validado un serializador como en el ejemplo de la documentación? 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']
Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para tener en cuenta todos los errores de validación en UserRegistrationSerializer, podemos usar el método is_valid() provisto por DRF, y luego acceder al diccionario errors para obtener todos los errores de validación del serializador.

    En el ejemplo dado, podemos modificar el caso de prueba de la siguiente manera:

    def test_user_registration_invalid_confirmation(self):
        valid = self.serializer.is_valid()
        self.assertEqual(valid, False)
        expected_errors = {
            'username': [serializers.ValidationError('Choose a different username')],
            'password2': [serializers.ValidationError('Password confirmation failed')]
        }
        self.assertEqual(self.serializer.errors, expected_errors)
    

    Aquí, primero verificamos si el serializador es válido usando is_valid(). Si no es válido, verificamos el diccionario errors para verificar si contiene todos los errores de validación esperados.

    Creamos un diccionario expected_errors con las claves como los nombres de campo y los valores como listas de instancias serializers.ValidationError con los errores de validación esperados. Luego comparamos este diccionario con el diccionario errors devuelto por el serializador para asegurarnos de que se tengan en cuenta todos los errores de validación.

    Con esta modificación, deberíamos obtener la salida esperada de:

    {
        'username': [ErrorDetail(string='Choose a different username', code='invalid')],
        'password2': [ErrorDetail(string='Password confirmation failed', code='invalid')]
    }
    

Comments are closed.