Django Rest框架数据库错误异常处理

aro*_*ooo 5 python django django-rest-framework

HTTP_400_STATUS当存在数据库异常时,有没有办法让Django Rest Framework自动响应?

(IntegrityError等等)

示例:我有一个具有唯一用户名字段的模型,我正在尝试使用泛型rest_framework.ListCreateAPIView.HTTP_400_STATUS如果序列化程序验证失败,则通常会自动抛出,但这实际上是有效的输入,在db中无效.我该怎么办?

pun*_*lly 9

使用rest_framework正确的(使用休息框架样式响应)执行此操作:

from django.db import IntegrityError
from rest_framework import status
from rest_framework.generics import ListCreateAPIView
from rest_framework.response import Response

class MyListCreateAPIView(ListCreateAPIView):
    def create(self, request, *args, **kwargs):
        try:
            return super(ListCreateAPIView, self).create(request, *args, **kwargs)
        except IntegrityError:
            content = {'error': 'IntegrityError'}
            return Response(content, status=status.HTTP_400_BAD_REQUEST)
Run Code Online (Sandbox Code Playgroud)

以下是可用的HTTP 400状态代码列表


Kal*_*Kal 8

虽然覆盖通用视图是一个完全有效的解决方案,但我认为一个更好的解决方案是利用Django REST Frameworks的选项来实现自定义异常处理。为此,您可以创建一个处理程序函数,该函数将API视图中引发的异常转换为响应对象。为此,您需要做的就是通过在设置中覆盖Django REST Framework自定义处理程序的位置:

REST_FRAMEWORK = {'EXCEPTION_HANDLER':'my_project.my_app.utils.custom_exception_handler'}
Run Code Online (Sandbox Code Playgroud)

在指定的文件内(my_project.my_app.utils.py在这种情况下),您将执行以下操作:

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):
    # Call REST framework's default exception handler first to get the standard error response.
    response = exception_handler(exc, context)

    # if there is an IntegrityError and the error response hasn't already been generated
    if isinstance(exc, IntegrityError) and not response:
        response = Response(
            {
                'message': 'It seems there is a conflict between the data you are trying to save and your current '
                           'data. Please review your entries and try again.'
            },
            status=status.HTTP_400_BAD_REQUEST
        )

    return response
Run Code Online (Sandbox Code Playgroud)

正如文档所说,值得注意的是“将仅针对引发的异常生成的响应调用异常处理程序”。(即,仅当您执行以下操作时:)serializer.is_valid(raise_exception=True)。但是,这仅在您自称“serializer.is_valid()自定义时才重要,因为“通用视图使用了raise_exception = True标志,这意味着您可以在API中全局覆盖验证错误响应的样式。为此,请使用自定义异常处理程序,如下所示:如上所述。” 另外,我只是想指出,如果你想指定自定义IntegrityError在一个给定的视图的消息后,那么你总是可以覆盖通用视图为其他答案证明和自定义异常处理程序将不插入默认的消息response将不不再None


Seb*_*zny 6

您应该通过返回 a来扩展ListCreateAPIView和捕获IntegrityError并处理它bad_request

from django.views.defaults import bad_request
from rest_framework.generics import ListCreateAPIView

class MyListCreateAPIView(ListCreateAPIView):

    def create(self, request, *args, **kwargs):
        try:
            return super(ListCreateAPIView,self).create(request, *args, **kwargs)
        except IntegrityError:
            return bad_request(request)
Run Code Online (Sandbox Code Playgroud)

有趣的是,您可以提出 aSuspiciousOperation而不是明确返回 bad_request :

        except IntegrityError:
            from django.core.exceptions import SuspiciousOperation
            raise SuspiciousOperation
Run Code Online (Sandbox Code Playgroud)

然后 django 将返回一个400 BAD REQUEST.