drf 默认返回的异常格式是这样的
{
"username": [
"该字段是必填项。"
],
"password": [
"该字段是必填项。"
]
}
但是在实际工作中、这样的数据不利于前端的渲染
就拿写IOS的AFNetworking为例、他判断请求成功还是失败不是以http的状态码判断的(当然也可以自己封装)
一般判断返回的code作为判断条件
当错误返回的时候直接使用response[@"error"]作为错误的提示信息
ps:response是数据返回的字典 error是错误信息的key
一般是这样的格式返回(有错误的时候)
{
"msg": "username该字段是必填项。",
"code": 0,
"data": ""
}
正确的时候
{
"msg": "success",
"code": 1,
"data": {
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTU4NjMxMDk5NCwianRpIjoiZTkzZDlhYzZhMWM5NDQ2NTgyN2ZkMzJmNWYzNDVlNjIiLCJ1c2VyX2lkIjoxfQ.Nca8X5AClJxVuDK1-wxJBFZI9WzXt2UL3bytyRckqTU",
"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTg1NjE5Nzk0LCJqdGkiOiI0NjZkMzk2ZThiMjU0MDQxYTE5OWJjZTc5MjRjNDc2ZiIsInVzZXJfaWQiOjF9.9oaLarHvtT8Zo9dV312Y5fE9HtkTp9Uxrx4WWo_8etg",
"username": "hahn",
"user_id": 1
}
}
想要弄成这样的效果需要自定义drf异常返回和自定义数据返回格式
在settings.py中
EXCEPTION_HANDLER对应的是你文件夹路径
# drf配置
REST_FRAMEWORK = {
# 全局配置异常模块
'EXCEPTION_HANDLER': 'pine_mountain_bridge.utils.exception.custom_exception_handler',
# 修改默认返回JSON的renderer的类
'DEFAULT_RENDERER_CLASSES': (
'pine_mountain_bridge.utils.rendererresponse.customrenderer',
),
}
设置异常返回
这里我是在pine_mountain_bridge的utils文件夹里面新建了exception.py文件
这里可以根据你的需求修改、我这个只是参考
# 自定义异常处理
from rest_framework.views import exception_handler
from rest_framework.views import Response
from rest_framework import status
# 将仅针对由引发的异常生成的响应调用异常处理程序。它不会用于视图直接返回的任何响应
def custom_exception_handler(exc, context):
response = exception_handler(exc, context)
# 这个循环是取第一个错误的提示用于渲染
for index, value in enumerate(response.data):
if index == 0:
key = value
value = response.data[key]
if isinstance(value, str):
message = value
else:
message = key + value[0]
if response is None:
# print(exc) #错误原因 还可以做更详细的原因,通过判断exc信息类型
# print(context) #错误信息
# print('1234 = %s - %s - %s' % (context['view'], context['request'].method, exc))
return Response({
'message': '服务器错误'
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=True)
else:
# print('123 = %s - %s - %s' % (context['view'], context['request'].method, exc))
return Response({
'message': message,
}, status=response.status_code, exception=True)
return response
设置自定义返回数据结构
这里我是在pine_mountain_bridge的utils文件夹里面新建了rendererresponse.py文件
这里可以根据你的需求修改、我这个只是参考
'''
自定义返回处理
'''
# 导入控制返回的JSON格式的类
from rest_framework.renderers import JSONRenderer
class customrenderer(JSONRenderer):
# 重构render方法
def render(self, data, accepted_media_type=None, renderer_context=None):
if renderer_context:
if isinstance(data, dict):
msg = data.pop('msg', 'success')
code = data.pop('code', 1)
else:
msg = 'success'
state = 1
# 重新构建返回的JSON字典
for key in data:
# 判断是否有自定义的异常的字段
if key == 'message':
msg = data[key]
data = ''
code = 0
ret = {
'msg': msg,
'code': code,
'data': data,
}
# 返回JSON数据
return super().render(ret, accepted_media_type, renderer_context)
else:
return super().render(data, accepted_media_type, renderer_context)
完成了
到这一步就可以返回这样的结构了
PS:可以和serializers里面的error_messages一起使用
默认提示
{
"msg": "name该字段是必填项。",
"state": 0,
"data": ""
}
在自己对于的serializers文件中设置error_messages
name = serializers.CharField(
error_messages={
"blank": "请输入名字",
"required": "请输入名字",
},
)
自定义返回
如果不想有name这个key请修改自定义异常exception.py的代码
{
"msg": "name请输入名字",
"state": 0,
"data": ""
}