Messaggi di errore personalizzati nel serializzatore Django Rest Framework

Lo scenario è abbastanza semplice:

Ho un modello con alcuni campi che sono richiesti. Diciamo che uno di loro è un campo di TextField che non può essere blank . Ho anche un ModelSerializer (Django Rest Framework) che rappresenta quel modello.

Quando una stringa vuota viene utilizzata per impostare quel campo attraverso il serializzatore, l’errore restituito proviene dal modello stesso ( This field can't be blank ).

Vorrei sovrascrivere i messaggi di errore solo a livello di serializzatore, senza la necessità di ridefinire esplicitamente ogni campo nel serializzatore (che credo sia contrario al principio DRY), dover scrivere un metodo validate_ per ogni campo e aumentare il mio possedere ValidationError o dover modificare i messaggi di errore a livello di Model (perché a volte il contesto del messaggio di errore è importante per il mio caso d’uso e il messaggio di errore dovrebbe essere fornito di conseguenza).

In altre parole, esiste un modo per sovrascrivere i messaggi di errore nel livello del serializzatore così semplice come per 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")}} 

EDIT: Vedo che questa domanda riceve ancora alcune visualizzazioni, quindi è importante notare che c’è un altro approccio, molto più pulito rispetto alla risposta originale che ho postato qui.

Puoi semplicemente usare l’attributo extra_kwargs della class Meta del serializzatore, in questo modo:

 class UserSerializer(ModelSerializer): class Meta: model = User extra_kwargs = {"username": {"error_messages": {"required": "Give yourself a username"}}} 

Risposta originale:

Usando la risposta di @mariodev ho creato una nuova class nel mio progetto che lo fa:

 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) 

Il primo offre la possibilità di aggiungere un nuovo attributo di class Meta al serializzatore come con ModelForm . Il secondo eredita da ModelSerializer e utilizza la tecnica di @ mariodev per aggiornare i messaggi di errore.

Tutto ciò che resta da fare è semplicemente ereditarlo e fare qualcosa del genere:

 class UserSerializer(CustomErrorMessagesModelSerializer): class Meta: model = User error_messages = {"username": {"required": "Give yourself a username"}} 

Nel tuo serializzatore:

 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' 

Si prega di notare che alcuni messaggi di errore sono costituiti da %s segnaposto come:

 'invalid': _("'%s' value must be either True or False."), 

per BooleanField .

Quindi è necessario andare oltre la parte di default_error_messages in ogni tipo di campo nei fields.py del DRF, per usarlo correttamente.

error_messages sembrava essere ignorato da error_messages , quindi ho dovuto adottare un approccio diverso.

 email = serializers.EmailField(validators=[ UniqueValidator( queryset=models.Client.objects.all(), message="My custom error", )] ) 

È più semplice (ma meno flessibile, meno riutilizzabile) di @ gabriel-amram, ma molto meno hacky di quello di @ mariodev.

Un altro approccio per UniqueValidator (per l’utilizzo 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 da quando ho giocato per un po ‘, se stai usando qualcosa come un URLField che aggiunge solo un URLValidator, non sembra usare i messaggi error_messages , quindi ho fatto qualcosa di simile alla risposta di @ Hugo:

 class Meta: extra_kwargs = {"url_field": {"validators": [validators.URLValidator(message="My error message")]}} 

DRF3.0 si aspetta che definiamo esplicitamente i validatori per i campi se vogliamo sovrascrivere i validatori di modello predefiniti. Questo può essere fatto passando extra_kwargs e definendo esplicitamente i validatori per qualsiasi campo tu sembri necessario. Inoltre puoi anche specificare il tuo validatore personalizzato che può essere riutilizzato per diversi campi o anche altri serializzatori

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,]}}