DRF自定义异常为何返回500而非202?能否重写__init__方法?
自定义API异常的问题分析与解决办法
首先给你吃个定心丸:完全可以在自定义异常类里用__init__方法,你遇到的NameError是因为类属性的初始化时机搞错了,和__init__本身没关系。
为啥会报错?
看你写的异常类代码:
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'
这里的default_detail是类级别的属性,在Python解析这个类的定义时就会执行format(self.obj),但这时候连类的实例都还没创建,self根本不存在,自然就抛出name 'self' is not defined的错误了。
正确的写法有两种
Django REST Framework的APIException设计很灵活,我们可以用两种方式实现你的需求:
方式一:在__init__里动态设置详情信息
把detail作为实例属性来设置,避开类初始化时的时机问题:
class CustomExcep(APIException): # 把固定的类属性放在这里 status_code = 202 default_code = 'accepted' def __init__(self, obj): super().__init__() # 动态生成详情文本,赋值给实例的detail属性 self.detail = f'This already exists.{obj}'
方式二:复用父类的detail参数(更简洁)
其实APIException的构造方法本身就支持传入detail参数,我们可以直接利用这个特性:
class CustomExcep(APIException): status_code = 202 default_code = 'accepted' def __init__(self, obj): # 先拼接好详情文本,再传给父类的构造方法 detail_text = f'This already exists.{obj}' super().__init__(detail=detail_text)
顺便提下你的序列化器方法
原代码里的duplicate_check还有个小问题:name和age变量没定义,你得从序列化器的验证数据里取,比如这样:
def duplicate_check(self): name = self.validated_data.get('name') age = self.validated_data.get('age') if Person.objects.filter(name=name, age=age).exists(): raise CustomExcep('Person') return True
为啥移除__init__能正常跑?
当你删掉__init__直接抛CustomExcep()时,异常类会用默认的default_detail——不过你原代码里的default_detail写法本来就有问题,可能你当时临时改成了不带self的内容?总之核心是,只要分清类属性和实例属性的初始化时机,__init__完全可以正常使用。
内容的提问来源于stack exchange,提问作者david
相关产品推荐
相关产品推荐

