1.自定义异常处理(custom_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
2.自定义正常返回(render_response.py)
点击查看代码
'''
自定义返回处理
'''
# 导入控制返回的JSON格式的类
from rest_framework.renderers import JSONRenderer
class MyRender(JSONRenderer):
# 重构render方法
def render(self, data, accepted_media_type=None, renderer_context=None):
if renderer_context:
if isinstance(data, dict):
msg = data.pop('msg', '成功')
code = data.pop('code', 0)
data = data.pop('data', data)
if isinstance(data, list):
data = {
'total': len(data),
'data': data
}
elif isinstance(data, list):
msg = '成功'
code = 0
data = {
'total': len(data),
'data': data
}
else:
msg = 'success'
code = 0
# 重新构建返回的JSON字典
for key in data:
# 判断是否有自定义的异常的字段
if key == 'message':
msg = data[key]
data = ''
code = 1
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)
通过以上三步,drf返回的数据格式就会变成以下形式单个返回:批量返回
异常返回
优化
通过上边三不,就可以实现有状态码的返回报文。但是状态码就是在自定义返回中写的0,1两种。如果需要其他状态码,就需要用
return Response({'code': 111, 'msg': 'hahah', 'data': qs})
这种形式组报文。对于这种,可以重写Response来优化。
重写Response
点击查看代码
from rest_framework.response import Response
class APIResponse(Response):
def __init__(self, code=0, msg='success', data=None, status=None,
template_name=None, headers=None,
exception=False, content_type=None, **kwargs):
dic = {'code': code, 'msg': msg}
if data:
dic['data'] = data
if kwargs:
dic.update(kwargs)
super().__init__(data=dic, status=status,
template_name=template_name, headers=headers,
exception=exception, content_type=content_type)
用重写的Response类返回数
qs = list(Camp.objects.filter(status=0).values())
return APIResponse(qs)
drf公共类
使用上边重写后的APIResponse,并对分页重写。
点击查看代码
from rest_framework import status
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
class APIResponse(Response):
def __init__(self, code=0, msg='成功', data=None, status=None,
template_name=None, headers=None,
exception=False, content_type=None, **kwargs):
dic = {'code': code, 'msg': msg}
if data:
dic['data'] = data
if kwargs:
dic.update(kwargs)
super().__init__(data=dic, status=status,
template_name=template_name, headers=headers,
exception=exception, content_type=content_type)
class StandardResultsSetPagination(PageNumberPagination):
page_size = 100
page_size_query_param = 'page_size'
max_page_size = 1000
class DRFBaseViewSet(ModelViewSet):
pagination_class = StandardResultsSetPagination
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return APIResponse(data=serializer.data)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return APIResponse(data=serializer.data)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return APIResponse(data=serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
return APIResponse(data=serializer.data)
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return APIResponse(status=status.HTTP_204_NO_CONTENT)