为什么DRF自定义异常会提高500而不是202?

时间:2018-05-23 17:37:31

标签: django django-rest-framework

例外

class CustomExcep(APIException):
    def __init__(self, obj):
    super(CustomExcep, self).__init__()
    self.obj = obj

status_code = 202
default_detail = 'This already exists.{}'.format(self.obj)
default_code = 'accepted'

在序列化程序中

def duplicate_check(self):
    if Person.objects.filter(name=name, age=age).exists():
        raise CustomExcep('Person')
    return True

错误:

<tr>
  <th>Exception Type:</th>
  <td>NameError</td>
</tr>


<tr>
  <th>Exception Value:</th>
  <td><pre>name &#39;self&#39; is not defined</pre></td>
</tr>

这导致一般500错误而没有其他信息。 如果我删除 init 方法并且只是在不传递任何内容的情况下引发CustomExcep,则会按预期返回202.

我可以不将init用于异常类吗?

1 个答案:

答案 0 :(得分:0)

TL; DR:您没有在__init__

上调用超级

当您举起APIException时,会调用dunder方法__str__。以下是DRF课程__init____str__APIException的声明:

class APIException(Exception):
    """
    Base class for REST framework exceptions.
    Subclasses should provide `.status_code` and `.default_detail` properties.
    """
    status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
    default_detail = _('A server error occurred.')
    default_code = 'error'

    def __init__(self, detail=None, code=None):
        if detail is None:
            detail = self.default_detail
        if code is None:
            code = self.default_code

        self.detail = _get_error_details(detail, code)

    def __str__(self):
        return six.text_type(self.detail)

如您所见,init方法设置self.detail属性,该属性由__str__引用。您看到500错误的原因是您的代码中存在内部服务器错误; self.detail正在筹集AttributeError

将您的代码更改为:

class CustomExcep(APIException):
    def __init__(self, obj):
        super(CustomExcep, self).__init__()
        ... your code here

甚至更好;定义CustomExcep如下:

class CustomExcep(APIException):
    default_code = 202
    default_detail = 'Instance already exists'

其他几个问题:

  • 您在当前的实现中传递字符串'Person'而不是对象'Person'
  • 您班级中__init__的签名与__init__班级中APIException的基础签名不同。

第二期的更新

您的代码中存在污点问题,这应该是它的外观:

class CustomExcep(APIException):
    status_code = 202
    default_detail = 'This already exists.{}'.format(self.obj)
    default_code = 'accepted'

    def __init__(self, obj):
        super(CustomExcep, self).__init__()
        self.obj = obj

status_codedefault_detaildefault_code是类属性,它们需要通过缩进嵌套在类声明中。