在 Django REST 中引发异常

Posted

技术标签:

【中文标题】在 Django REST 中引发异常【英文标题】:Raising Exceptions in Django REST 【发布时间】:2015-10-24 07:18:35 【问题描述】:

我正在尝试在 django rest 框架中测试异常。 基于http://www.django-rest-framework.org/api-guide/exceptions/raise NotFound,

默认情况下,此异常会导致带有 HTTP 状态的响应 代码“404 未找到”。

但是,当我发出 GET(到 /example1)时,我得到一个 500 ,

Request Method: GET
Request URL:    http://192.168.59.103:8002/example1
Django Version: 1.8.3
Exception Type: NotFound
Exception Value:    
not found
Exception Location: /home/djangoapp/testtools/api/views.py in example1, line 7
Python Executable:  /usr/bin/python

详情如下,

settings.py

REST_FRAMEWORK = 'EXCEPTION_HANDLER':'rest_framework.views.exception_handler'

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
)

urls.py

from django.conf.urls import include, url
from api import views

urlpatterns = [
    url(r'example1', views.example1),
]

views.py

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.exceptions import APIException,ParseError,NotFound

def example1(request):                                                                                                                               
    raise NotFound("not found")

有什么想法吗?

【问题讨论】:

在您对@ArpitGoyal 的回答中,您说您实际上想知道如何为任何 URL 生成您自己的 404 响应,而不仅仅是此示例代码。如果这是真的,你能澄清一下这个问题吗? 【参考方案1】:
from rest_framework.exceptions import NotFound

NotFound 类是从APIException 扩展而来的。 APIException 的默认状态码是500 Internal Server Error,而NotFound 的默认状态码是404

因此,根据我的说法,您正试图在纯 django 视图中抛出 rest framework 异常。我在这里写了一个测试用例来检查引发错误的几率是多少。猜猜一个试图引发rest framework 异常的简单django 视图不会被视为视图错误。但是在提供装饰器并将其声明为 API 视图时,它会进入 exception_handler

所以当你这样做时:

from rest_framework.decorators import api_view

@api_view()
def example1(request):
    raise NotFound('not found')

这现在被识别为由 API 引发的异常,该异常进入您提供的默认 rest_framework EXCEPTION_HANDLER,并返回任何给定异常的响应。

它的docstring 说:

返回应该用于任何给定异常的响应。经过 默认我们处理 REST 框架 APIException,还有 Django 的 内置ValidationErrorHttp404PermissionDenied 例外。任何未处理的异常都可能返回None,这将 导致引发 500 错误。

【讨论】:

好酷。说得通。此外,如果我随后抛出对 /example2 的请求,这是否应该不会引发 DRF 的 NotFound 而无需我配置任何其他内容。 如果代码保持不变,每个 url 的行为应该相同。 好的,我一定是遗漏了一些东西,因为它无法自动生成 404 JSON 响应 任何想法。你的答案回答了 90% 的问题,这只是最后一点。 我没听懂你。我唯一能想到的就是这样。 NotFound 是一个 api 异常,您只能在 APIView 上将其作为错误引发。在纯 django 视图中,它被识别为内部服务器错误。最后一部分是什么意思?【参考方案2】:

我不确定你为什么要这样做。这是 DRF 在找不到资源时使用的内部异常。但是您在任何 DRF 机器之外的标准 Django 视图中使用它。如果你想这样做,你应该使用标准的 Django 异常:

from django.core.exceptions import Http404

def example1(request):
    raise Http404('not found')

【讨论】:

【参考方案3】:

尝试使用匹配所有可能 url 的正则表达式更改您的 url,并将其放在主 urls.py 的末尾

例如:

urlpatterns = [
url(r'^(?P<slug>[\w-]+)/', views.example1),
]

【讨论】:

以上是关于在 Django REST 中引发异常的主要内容,如果未能解决你的问题,请参考以下文章

可以在 Django transaction.atomic() 中捕获并重新引发异常吗?

无效的凭据引发身份验证突变异常

Django REST Framework:当 POST 上存在额外字段时引发错误

Django REST 异常

从 django 模型的保存方法中引发 ValidationError?

Django-rest-framework 中的全局异常处理