Процесс обработки и UniqueConstraint Django

Я сделал модель с ограничениями:

class DiscountSchema(models.Model):
    ...
    class Meta:
        verbose_name = "DiscountSchema"
        constraints = [
            constraints.UniqueConstraint(
                fields=(
                    "level",
                    "level_value",
                    "discount_rate",
                    "background_col",
                    "foreground_col",
                    "loyalty_card",
                ),
                violation_error_message="UNIQUEERROR",
                name="Uniqueschema",
            )
        ]

Как я могу обработать эти ограничения при создании экземпляра в сериализаторе? Сейчас у меня есть:

        try:
            serializer.is_valid(raise_exception=True)
            return serializer.save()
        except IntegrityError as e:
            if "Uniqueschema" in e.args[0]:
                pass
            else:
                raise e

Есть ли лучший способ?

Предполагая, что вы используете CreateView какого-то типа (ListCreateView, или ModelViewSet и т.д.), вы могли бы переопределить метод create, который мог бы быть немного чище?

class DiscountSchema(ListCreateView):
    ...

    def create(self, request, *args, **kwargs):
        try:
            return super().create(request, *args, **kwargs)
        except IntegrityError:
            return Response(status=400)

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

Вы регистрируете свой обработчик в DRF в настройках:

REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'api.handlers.custom_exception_handler'}

(замените значение на то, куда вы поместили свой обработчик)

Затем определите что-то вроде этого для вашего обработчика:


from __future__ import unicode_literals
from django.db import IntegrityError
from rest_framework.views import Response, exception_handler
from rest_framework import status


def custom_exception_handler(exc, context):
    response = exception_handler(exc, context)
    if isinstance(exc, IntegrityError) and not response:
        response = Response(
            {'message': '<your error message here>'},
            status=status.HTTP_400_BAD_REQUEST,
        )
    return response

Помните, что если вы решите использовать свой собственный обработчик исключений, то при вызове serializer.is_valid() вручную в любом месте вашего кода (например, если вы переопределили какие-либо наборы представлений DRF и вызвали serializer.is_valid()), вам нужно будет добавить raises_exception к вызову is_valid() следующим образом serializer.is_valid(raise_exception=True). Чтобы запустить ваш обработчик исключений, ему необходимо поднять исключение.

Надеюсь, это поможет!

Вернуться на верх