Django ModelViewSet возвращает полную ошибку HTML 500 при дублировании поля, установленного в unique=true
Я пытаюсь исправить это все утро, но, похоже, не могу найти проблему. У меня есть конкретный API, возвращающий ошибку IntegrityError
дублирующего ключа в виде трассировки ошибки Django HTML вместо того, чтобы возвращать детальную ошибку (JSON) на поле формы.
Тип исключения: IntegrityError at /api/chats/ Значение исключения: дублирующее значение ключа нарушает уникальное ограничение "chats_chat_title_853c3234_uniq" ПОДРОБНАЯ ИНФОРМАЦИЯ: Ключ (title)=(Новый чат) уже существует.
Модель с полем заголовка, установленным на уникальность:
class Chat(TimestampedModel):
"""
A chat between multiple users.
"""
uuid = models.UUIDField(default=uuid4, null=False)
title = models.CharField(
max_length=255, null=False, unique=True, blank=False)
Сериализатор для чата:
class ChatSerializer(serializers.ModelSerializer):
title = serializers.CharField(max_length=255)
def create(self, validated_data):
"""
Creates a new Chat and adds the m2m employees to it
"""
user = self.context['request'].user
title = validated_data['title']
# Add the user to the chat
employee_ids = validated_data.pop("employee_ids")
employee_ids.append(user.id)
# Create and save the chat
# Add the employees to the chat
# Add the sender to the chat
chat = Chat.objects.create(created_by=user, title=title)
chat.employees.set(employee_ids)
chat.employees.add(user)
chat.save()
return chat
И ViewSet:
class ChatViewSet(MixedPermissionModelViewSet):
lookup_field = 'uuid'
queryset = Chat.objects.all()
serializer_class = ChatSerializer
permission_classes_by_action = {
'list': [IsAuthenticated],
'create': [IsAuthenticated],
'update': [IsAuthenticated],
'retrieve': [IsAuthenticated],
'partial_update': [IsAuthenticated],
'destroy': [IsAuthenticated]
}
def add_user_has_viewed(self, chat):
if self.request.user in chat.employees.all():
chat.has_viewed.add(self.request.user)
chat.save()
return chat
def perform_create(self, serializer):
chat = serializer.save()
self.add_user_has_viewed(chat)
Это специфично для данного API при создании объекта. Что я упускаю?
Вероятно, это происходит потому, что исключение IntegrityError
возникает на уровне ORM и не обрабатывается стандартным обработчиком исключений Django Rest Framework.
Лучший способ исправить это, не переписывая внутренности ViewSet
- определить пользовательский обработчик исключений, как описано здесь .
from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
from django.db import IntegrityError
def integrity_error_exception_handler(exc, context):
response = exception_handler(exc, context)
if isinstance(exc, IntegrityError) and not response:
response = Response({'detail': 'Your error message'}, status=status.HTTP_400_BAD_REQUEST)
return response
Затем добавьте этот обработчик в settings.py
REST_FRAMEWORK = {
...
'EXCEPTION_HANDLER': 'utils.exceptions.integrity_error_exception_handler'
}
Кроме того, вы можете использовать параметры exc
и context
для доступа к исходному исключению и объекту представления, чтобы возвращать более общие ответы.