Создание пользовательских Exceptions в Django

Ошибки сериализации, возвращаемые Django Rest Framework, не так просто отображать во внешнем интерфейсе. Вот как он возвращает ошибки сериализации для распространенных ошибок регистрации пользователей:

{'username': ['This field is required.'], 'password': ['This field must be at least 8 chars'], 'email': ['This field cannot be blank']}

Пользовательскому интерфейсу трудно с этим справиться. Возможно, придется проделать большую работу, чтобы определить, к какому полю относится сообщение об ошибке. Интерфейсу также сложно анализировать кучу массивов на наличие ошибок.

Понятные сообщения об ошибках

Чтобы сделать сообщения об ошибках более понятными:

Во-первых, переопределите сообщения об ошибках по умолчанию в __init__ методе вашего сериализатора. Здесь меняем его так, чтобы он действительно говорил, с каким полем (то есть с именем пользователя вместо «Это поле») связана ошибка:

class UserSerializer(serializers.ModelSerializer):
    email = serializers.EmailField(required=True)
    username = serializers.CharField(required=True)
    password = serializers.CharField(min_length=8, required=True)

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

    def __init__(self, *args, **kwargs):
        super(UserSerializer, self).__init__(*args, **kwargs)
        self.fields["username"].error_messages["required"] = u"username is required"
        self.fields["username"].error_messages["blank"] = u"username cannot be blank"
        self.fields["email"].error_messages["required"] = u"email is required"
        self.fields["email"].error_messages["blank"] = u"email cannot be blank"
        self.fields["password"].error_messages[
            "min_length"
        ] = u"password must be at least 8 chars"

Определение пользовательского исключения(Exception)

В нашем новом файле с именем. exceptions.py мы просматриваем поля, в которых могли бы переопределить ошибку, и получить первый элемент в массиве.

Если для каждого поля есть несколько исключений, нас это не беспокоит, потому что, если пользователь исправит одно, он перейдет к следующему исключению.

from rest_framework.exceptions import ValidationError
from rest_framework.views import exception_handler


def base_exception_handler(exc, context):
    response = exception_handler(exc, context)

    # check that a ValidationError exception is raised
    if isinstance(exc, ValidationError):
        # here prepare the 'custom_error_response' and
        # set the custom response data on response object
        if response.data.get("username", None):
            response.data = response.data["username"][0]
        elif response.data.get("email", None):
            response.data = response.data["email"][0]
        elif response.data.get("password", None):
            response.data = response.data["password"][0]

    return response

Наконец, убедитесь, что вы указали settings.py, что используете новый обработчик исключений :

REST_FRAMEWORK = {
    "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "rest_framework.authentication.TokenAuthentication",
        "rest_framework.authentication.SessionAuthentication",
        "rest_framework.authentication.BasicAuthentication",
    ),
    "EXCEPTION_HANDLER": ("app.exceptions.base_exception_handler"),
}

Вот более понятное сообщение об ошибке!

Альтернативный текст


Вывод

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