6

Questo è il mio serializers.py (voglio creare un serializzatore per il modello utente built-in):Django Rest Framework - come creare messaggi di errore personalizzati per tutti i campi ModelSerializer?

from rest_framework import serializers 

from django.contrib.auth.models import User 

class UserSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = User 
     fields = ('username', 'password', 'email',) 

Sono consapevole che Django Resto quadro ha il proprio validatori dei campi, perché quando cerco di creare un utente che utilizza un nome utente già esistente, solleva un detto errore:

{'username': [u'This field must be unique.']} 

voglio personalizzare il messaggio di errore e farle dire "Questo nome utente è già preso Riprovare." piuttosto che dire "Questo il campo deve essere unico ".

Essa ha anche un built-in validatore regex, perché quando creo un nome utente con un punto esclamativo, si dice:

{'username': [u'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.']} 

voglio personalizzare il validatore regex in modo che si dice solo "Nome utente non valido ".

Come si personalizzano tutti i messaggi di errore di ciascun campo?

Nota: in base a questo post: Custom error messages in Django Rest Framework serializer posso fare:

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' 

Ma che cosa devo fare per i validatori 'unici' e 'regex'? Ho provato a fare

self.fields['username'].error_messages['regex'] = u'My custom required msg' 

e

self.fields['username'].error_messages['validators'] = u'My custom required msg' 

ma nessuno dei due ha funzionato.

risposta

5

Per sostituire messaggi di errore univoci o irregolari è necessario modificare il membro message dell'oggetto corrispondente del validatore. Questo potrebbe essere fatto utilizzando classe intermedia separata:

from django.core.validators import RegexValidator 
from rest_framework.validators import UniqueValidator 
from django.utils.translation import ugettext_lazy as _ 


class SetCustomErrorMessagesMixin: 
    """ 
    Replaces built-in validator messages with messages, defined in Meta class. 
    This mixin should be inherited before the actual Serializer class in order to call __init__ method. 

    Example of Meta class: 

    >>> class Meta: 
    >>>  model = User 
    >>>  fields = ('url', 'username', 'email', 'groups') 
    >>>  custom_error_messages_for_validators = { 
    >>>   'username': { 
    >>>    UniqueValidator: _('This username is already taken. Please, try again'), 
    >>>    RegexValidator: _('Invalid username') 
    >>>   } 
    >>>  } 
    """ 
    def __init__(self, *args, **kwargs): 
     # noinspection PyArgumentList 
     super(SetCustomErrorMessagesMixin, self).__init__(*args, **kwargs) 
     self.replace_validators_messages() 

    def replace_validators_messages(self): 
     for field_name, validators_lookup in self.custom_error_messages_for_validators.items(): 
      # noinspection PyUnresolvedReferences 
      for validator in self.fields[field_name].validators: 
       if type(validator) in validators_lookup: 
        validator.message = validators_lookup[type(validator)] 

    @property 
    def custom_error_messages_for_validators(self): 
     meta = getattr(self, 'Meta', None) 
     return getattr(meta, 'custom_error_messages_for_validators', {}) 

Poi si può solo ereditare questa mixin e aggiornare Meta classe:

class UserSerializer(SetCustomErrorMessagesMixin, serializers.HyperlinkedModelSerializer): 
    class Meta: 
     model = User 
     fields = ('url', 'username', 'email', 'groups') 
     custom_error_messages_for_validators = { 
      'username': { 
       UniqueValidator: _('This username is already taken. Please, try again'), 
       RegexValidator: _('Invalid username') 
      } 
     } 
+0

Hm, lei ha citato "Questo potrebbe essere fatto utilizzando classe intermedia separata". C'è un altro modo per farlo anche tu? Quello che inizialmente ho provato è stato usare il mio ModelSerializer originale, facendo "def validate_username:" e facendo i miei controlli e sollevando serializer.ValidationError() se mi sono imbattuto in un errore, ma per qualche motivo non funzionava. Questo era il mio post SO sul problema: http://stackoverflow.com/questions/30542249/djangorestframework-modelserializer-field-level-validation-is-not-working ma da quando hai detto che quello che hai mostrato era Un modo di farlo , pensi che sia anche il più efficiente? – user2719875

+1

Un altro modo è sostituire tutti i validatori per un campo usando il campo 'Meta.extra_kwargs'. Nota che dovresti fornire __all__ validators, perché sostituirà __all__ validators originali. Se le prestazioni sono importanti, è necessario fornire alcune informazioni aggiuntive, almeno - connessioni previste al secondo. Ma se vuoi sostituire, diciamo 10 o anche 100 messaggi, non vedrai alcuna differenza tra gli approcci suggeriti. – soon

+0

ah ok, capito. Grazie. A proposito, due ulteriori domande per chiarimenti: 1) qual è il motivo dell'utilizzo di "HyperlinkedModelSerializer" in questo caso piuttosto che di "ModelSerializer"? e 2) c'è una posizione standard in cui vanno usati i mixin personalizzati? O potrei semplicemente mettere la classe "SetCustomErrorMessagesMixin" nel mio file serializers.py? – user2719875

Problemi correlati