Closed GabrielLins64 closed 11 months ago
Hi @GabrielLins64,
On my
CustomUserSerializer(serializers.ModelSerializer)
I have the following username validator:extra_kwargs = { 'username': {'validators': [validate_cpf,]}, }
where
def validate_cpf(value): if not is_valid_cpf(value): raise ValidationError('O nome de usuário precisa ser um CPF válido.')
in the above, the package will not find the error code because it only checks the error_messages
of the serializer and its fields.
I've even tried using the DRF-way to defining validation errors, as mentioned in the docs:
class CustomUserSerializer(serializers.ModelSerializer): default_error_messages = {"invalid_username": "O nome de usuário precisa ser um CPF válido."} def validate_username(self, username): if not is_valid_cpf(username): self.fail('invalid_username') return username
In this case, I would have expected to see the code in the API schema with attr as non_field_error
because it was added to the default_error_messages
of the serializer.
...
{
"attr": "non_field_errors",
"code": "invalid_username",
"detail": "string"
},
...
So, can you please provide a minimal example: code (url, view, serializer) + the resulting API schema so I can investigate this more when I get some free time?
Also, check out the decorator extend_validation_errors
since it allows adding error codes to specific fields
@extend_validation_errors(["invalid_username"], field_name="username", actions=["create", "update"])
class UserViewSet(ModelViewSet):
...
Hi @ghazi-git , thank you for the fast reply!
I just tried the @extend_validation_errors decorator and it worked for the API schema, but not for the "Example value" (screenshots attached by the end of the msg).
This is the updated validator:
def validate_cpf(value):
if not is_valid_cpf(value):
raise ValidationError(detail='O nome de usuário precisa ser um CPF válido.', code='invalid_cpf')
The serializer:
class CustomUserSerializer(serializers.ModelSerializer):
groups = GroupSerializer(many=True, read_only=True)
class Meta:
model = CustomUser
fields = [
'id',
'username',
'password',
'first_name',
'last_name',
'email',
'phone',
'is_staff',
'is_superuser',
'created_at',
'groups',
]
extra_kwargs = {
'id': {'read_only': True},
'created_at': {'read_only': True},
'username': {'validators': [validate_cpf,]},
'is_staff': {'read_only': True},
'is_superuser': {'read_only': True},
'password': {'write_only': True},
}
# def validate_username(self, username):
# if not is_valid_cpf(username):
# raise serializers.ValidationError('O nome de usuário precisa ser um CPF válido.', code='invalid_cpf')
# return username
def validate_password(self, password):
if not is_valid_password(password):
raise serializers.ValidationError(
'A senha precisa ter no mínimo 8 caracteres, pelo meno 1 dígito, uma letra maiúscula, uma letra minúscula e um caractere especial (#?!@$%^&*-).')
return password
def create(self, validated_data):
user = super().create(validated_data)
user.set_password(validated_data['password'])
user.save()
return user
The view:
from rest_framework.generics import CreateAPIView
@extend_validation_errors(["invalid_cpf"], field_name="username", methods=['post'])
class CustomUserCreateView(CreateAPIView):
serializer_class = CustomUserSerializer
permission_classes = [IsAdminOrReadOnly]
The url:
urlpatterns = [
path('', CustomUserCreateView.as_view(), name='user-create'),
]
This is the resulting API schema:
It did saw the invalid_cpf
code, but the "Example value" doesn't bring it nor the specified error detail (I'm not sure if is this the expected behavior):
About the examples, that is the expected behavior: the package does not provide examples for 400 error responses due to their dynamic nature (though it does provide examples for other error responses 401, 403, ...). So, what's happening is that swagger UI is automatically generating examples when they are not provided (for each attr, it's showing an example with the first error code).
About the error code not showing up: taking your code, removing the @extend_validation_errors
decorator from the view and adding a default_error_messages
attribute to the serializer results in the error code showing up in swagger UI. The addition of the error code to the default_error_messages
is required for it to show up.
class CustomUserSerializer(serializers.ModelSerializer):
default_error_messages = {"invalid_cpf": "O nome de usuário precisa ser um CPF válido."}
...
Oh, ok. Thank you!
Hi, I'm using
On my
CustomUserSerializer(serializers.ModelSerializer)
I have the following username validator:where
I actually get the correct response when sendind a wrong payload via postman:
However, the swagger schema seems to fail in finding the validation for this code:
I've even tried using the DRF-way to defining validation errors, as mentioned in the docs:
But this also doesn't work. Am I missing something?