1.全局异常
```python
from rest_framework.exceptions import ValidationError
from rest_framework.views import exception_handler
def custom_exception_handler(exc, context):
"""
自定义异常,需要在 settings.py 文件中进行全局配置
1.在视图中的 APIView 中使用时,需要在验证数据的时候传入 raise_exception=True 说明需要使用自定义异常
2.ModelViewSet 中非自定义 action 已经使用了 raise_exception=True,所以无需配置
"""
response = exception_handler(exc, context)
if response is not None:
# 字段校验错误处理
if isinstance(exc, ValidationError):
if isinstance(response.data, dict):
# 取错误信息中的一组数据返回
error_data = list(dict(response.data).items())[0]
# 该组数据的 key ,对应模型中的某个字段
error_key = error_data[0]
# 该组数据的 value ,有可能是多个错误校验提示信息,这里只取第一条
error_value = error_data[1][0]
response.data['message'] = f"{error_key}: {error_value}"
for key in dict(response.data).keys():
# 删除多余错误信息
if key != 'message':
response.data.pop(key)
response.data['code'] = 40000
response.data['data'] = None
if isinstance(response.data, list):
response.data = {'code': 40000, 'message': response.data[0], 'data': None}
return response
if 'detail' in response.data:
response.data = {'code': 40000, 'message': response.data.get('detail'), 'data': None}
else:
# 未知错误
response.data = {'code': 40000, 'message': str(response.data), 'data': None}
return response
return response
```
2.自定义 response
```python
from rest_framework.response import Response
from rest_framework import serializers
class JsonResponse(Response):
"""
自定义接口响应数据格式类
1.在视图类中的 APIView 中使用该 JsonResponse 返回响应数据
2.ModelViewSet 、Mixin 下派生的 APIView 类、views.APIView 都需要自己重写并返回 JsonResponse 格式的数据
"""
def __init__(self, data=None, code=None, msg=None,
status=None,
template_name=None, headers=None,
exception=False, content_type=None):
super().__init__(None, status=status)
if isinstance(data, serializers.Serializer):
msg = (
'You passed a Serializer instance as data, but '
'probably meant to pass serialized `.data` or '
'`.error`. representation.'
)
raise AssertionError(msg)
self.data = {'code': code, 'message': msg, 'data': data}
self.template_name = template_name
self.exception = exception
self.content_type = content_type
if headers:
for name, value in headers.items():
self[name] = value
```
ModelViewSet 子类中重写 action 返回值
```python
from utils.drf_utils.custom_json_response import JsonResponse
def create(self, request, *args, **kwargs):
"""
create task
"""
res = super().create(request, *args, **kwargs)
return JsonResponse(data=res.data, msg='success', code=20000, status=status.HTTP_201_CREATED,
headers=res.headers)
```