6

Это мой serializers.py (я хочу создать сериалайзер для встроенной модели пользователя):Django Rest Framework - как создать персонализированные сообщения об ошибках для всех полей 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',) 

Я знаю, что Django Rest Framework имеет собственные валидаторы поля, потому что, когда я пытаюсь создать пользователя с именем пользователя, который уже существует, он поднимает поговорку об ошибке:

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

Я хочу, чтобы настроить сообщение об ошибке и сделать его сказать: «Это имя пользователя уже занято Пожалуйста, попробуйте еще раз.», а не говорить «Это поле должно быть уникальным ».

Он также имеет встроенный в регулярное выражение валидатора, потому что, когда я создаю имя пользователя с восклицательным знаком, он говорит:

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

Я хочу, чтобы настроить регулярное выражение валидатора, так что он просто говорит: «Неверное имя пользователя ».

Как настроить все сообщения об ошибках, которые имеют каждое поле?

Примечания: согласно этому сообщению: Custom error messages in Django Rest Framework serializer я могу сделать:

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' 

Но что делать для «уникальных» и валидаторов «регулярных выражения»? Я пытался делать

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

и

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

но ни работал.

ответ

5

Чтобы заменить сообщения об ошибках с уникальными или регулярными выражениями, вы должны изменить член соответствующего объекта валидатора message. Это может быть сделано с помощью отдельного подмешать класс:

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', {}) 

Тогда вы могли бы просто наследовать этот подмешать и обновить Meta класс:

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

Хм, вы сказали «Это может быть сделано с помощью отдельного класса подмешать». Есть ли другой способ сделать это? Первоначально я пытался использовать мой оригинальный ModelSerializer, выполняя «def validate_username:» и выполняя свои собственные проверки и поднимая serializer.ValidationError(), если я столкнулся с ошибкой, но по какой-то причине это не сработало. Это было мое сообщение SO по этому вопросу: http://stackoverflow.com/questions/30542249/djangorestframework-modelserializer-field-level-validation-is-not-working, но поскольку вы упомянули, что то, что вы показали, было одним из способов сделать это , как вы думаете, это также наиболее эффективно? – user2719875

+1

Другой способ - заменить все валидаторы для поля, используя поле «Meta.extra_kwargs». Обратите внимание, что вы должны предоставить валидаторы __all__, потому что он заменит оригинальные валидаторы __all__. Если производительность важна, вы должны предоставить некоторую дополнительную информацию, по крайней мере - ожидаемые соединения в секунду. Но если вы хотите заменить, скажем, 10 или даже 100 сообщений, вы не увидите никакой разницы между предлагаемыми подходами. – soon

+0

ах, получилось. Благодарю. Кстати, еще два более быстрых вопроса для разъяснения: 1) в чем причина использования «HyperlinkedModelSerializer», а не просто «ModelSerializer»? и 2) есть ли стандартное место, куда идут пользовательские миксины? Или я могу просто поместить класс SetCustomErrorMessagesMixin в свой файл serializers.py? – user2719875

Смежные вопросы