fields - Mensajes de error personalizados en el serializador Django Rest Framework.
raise exception django rest framework (6)
DRF3.0 espera que definamos explícitamente los validadores para los campos si deseamos anular los validadores de modelo predeterminados. Esto se puede hacer pasando extra_kwargs y definiendo explícitamente los validadores para cualquier campo que parezca necesario. También puede especificar su propio validador personalizado que puede reutilizarse de nuevo para diferentes campos o incluso otros serializadores.
http://www.django-rest-framework.org/api-guide/serializers/#validation
http://www.django-rest-framework.org/api-guide/validators/#validation-in-rest-framework
# my_app/validators.py
def validate_required(value):
# whatever validation logic you need
if value == '''' or value is None:
raise serializers.ValidationError(''This field is required.'')
# my_app/serializers.py
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
extra_kwargs = {"field1": {"validators": [validators.validate_required,]}}
El escenario es bastante sencillo:
Tengo un modelo con algunos campos que son requeridos. Digamos que uno de ellos es un TextField
que no puede estar en blank
. También tengo un ModelSerializer
(Django Rest Framework) que representa ese modelo.
Cuando se usa una cadena vacía para establecer ese campo a través del serializador, el error devuelto proviene del propio modelo ( This field can''t be blank
).
Me gustaría anular los mensajes de error solo en el nivel de serializador, sin la necesidad de volver a especificar explícitamente cada campo en el serializador (que creo que está en contra del principio DRY), tener que escribir un método validate_
para cada campo y elevar mi propio ValidationError
o tener que cambiar los mensajes de error en el nivel del Model
(porque a veces el contexto del mensaje de error es importante para mi caso de uso y el mensaje de error debe darse en consecuencia).
En otras palabras, ¿hay una manera de anular los mensajes de error en el nivel de serializador tan fácil como es para un ModelForm
:
class MyModelForm(ModelForm):
class Meta:
model = MyModel
error_messages = {"field1": {"required": _("For some reason this is a custom error message overriding the model''s default")}}
En su serializador:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
def __init__(self, *args, **kwargs):
super(UserSerializer, self).__init__(*args, **kwargs)
self.fields[''username''].error_messages[''required''] = u''My custom required msg''
Tenga en cuenta que algunos mensajes de error consisten en %s
marcadores de posición como:
''invalid'': _("''%s'' value must be either True or False."),
para BooleanField
.
Por lo tanto, debe revisar la parte default_error_messages
en cada tipo de campo en el fields.py
del DRF, para usarlo correctamente.
Otro enfoque para UniqueValidator (para usar con ModelSerializer):
def __init__(self, *args, **kwargs):
super(UserSerializer, self).__init__(*args, **kwargs)
# Find UniqueValidator and set custom message
for validator in self.fields[''email''].validators:
if isinstance(validator, validators.UniqueValidator):
validator.message = _(''This email already exist on this site'')
Solo una nota, ya que jugué con esto por un tiempo, si estás usando algo como un campo de URL que solo agrega un URLValidator, no parece usar los mensajes de error, así que hice algo similar a la respuesta de @ Hugo:
class Meta:
extra_kwargs = {"url_field": {"validators": [validators.URLValidator(message="My error message")]}}
unique
error_messages
de error_messages
parecían ignorarse de forma unique
, por lo que tuve que adoptar un enfoque diferente.
email = serializers.EmailField(validators=[
UniqueValidator(
queryset=models.Client.objects.all(),
message="My custom error",
)]
)
Es más simple (pero menos flexible, menos reutilizable) que @ gabriel-amram, pero mucho menos intrépido que @ mariodev.
EDIT: Veo que esta pregunta aún recibe algunas opiniones, por lo que es importante tener en cuenta que hay otro enfoque, mucho más claro que la respuesta original que publiqué aquí.
Puedes usar el atributo extra_kwargs de la clase Meta del serializador, así:
class UserSerializer(ModelSerializer):
class Meta:
model = User
extra_kwargs = {"username": {"error_messages": {"required": "Give yourself a username"}}}
Respuesta original:
Usando la respuesta de @mariodev, creé una nueva clase en mi proyecto que hace eso:
from rest_framework.serializers import ModelSerializer, ModelSerializerOptions
class CustomErrorMessagesModelSerializerOptions(ModelSerializerOptions):
"""
Meta class options for CustomErrorMessagesModelSerializerOptions
"""
def __init__(self, meta):
super(CustomErrorMessagesModelSerializerOptions, self).__init__(meta)
self.error_messages = getattr(meta, ''error_messages'', {})
class CustomErrorMessagesModelSerializer(ModelSerializer):
_options_class = CustomErrorMessagesModelSerializerOptions
def __init__(self, *args, **kwargs):
super(CustomErrorMessagesModelSerializer, self).__init__(*args, **kwargs)
# Run through all error messages provided in the Meta class and update
for field_name, err_dict in self.opts.error_messages.iteritems():
self.fields[field_name].error_messages.update(err_dict)
El primero da la posibilidad de agregar un nuevo atributo de clase Meta
al serializador como con el ModelForm
. La segunda hereda de ModelSerializer
y utiliza la técnica de @ mariodev para actualizar los mensajes de error.
Todo lo que queda por hacer, es simplemente heredarlo, y hacer algo así:
class UserSerializer(CustomErrorMessagesModelSerializer):
class Meta:
model = User
error_messages = {"username": {"required": "Give yourself a username"}}