格式化DRF的Response的格式

为什么需要格式化Response

在现在前后端分离的web开发环境中,规范一致的接口返回格式会减少前后端打架的概率。

常见的返回的数据格式一般长这个样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"code": 200,
"message": "OK",
"data": {
"id": "user-4d51faba-97ff-4adf-b256-40d7c9c68103",
"firstName": "crifan",
"lastName": "Li",
"password": "654321",
"phone": "13511112222",
"createdAt": "2016-10-24T20:39:46",
"updatedAt": "2016-10-24T20:39:46"
}
}

DRF返回的数据默认是没有外边的code和message的,如果直接使用ModelViewSet,返回的数据大概是这个样子:

1
2
3
4
5
6
7
8
9
{
"id": "user-4d51faba-97ff-4adf-b256-40d7c9c68103",
"firstName": "crifan",
"lastName": "Li",
"password": "654321",
"phone": "13511112222",
"createdAt": "2016-10-24T20:39:46",
"updatedAt": "2016-10-24T20:39:46"
}

这样的数据格式对前端开发人员特别的不友好,经过探索,我终于发现了自动格式化返回数据的最佳方案;

如何格式化Response

在这里通过继承DRF的JSONRenderer,并重写render方法来实现数据的自动格式化

定义新的Renderer类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from rest_framework.renderers import JSONRenderer


class CustomJsonRender(JSONRenderer):

def render(self, data, accepted_media_type=None, renderer_context=None):

if renderer_context:
response = renderer_context['response']
msg = "OK"
code = response.status_code
if isinstance(data, dict):
# 这里实现自定义code和msg,如果你觉得默认的信息不够友好 可以在返回的字典里传入code,msg
msg = data.pop('msg', msg)
code = data.pop('code', code)
data = data.pop('data', data)
if not str(code).startswith("20") and data:
# 这里是为了在DRF出现以异常时格式化Response
msg = data.pop('detail', 'failed')
response.status_code = 200
res = {
'code': code,
'msg': msg,
'data': data,
}
return super().render(res, accepted_media_type, renderer_context)
else:
return super().render(data, accepted_media_type, renderer_context)

单独在APIView和ViewSet中使用

1
2
3
4
5
6
7
8
9
10
class SimpleView(APIView):
renderer_classes = (CustomJsonRender,)
def get(self, request):
# do something
return Response({"id":"xx"})

class SimpleViewSet(ModelViewSet):
renderer_classes = (CustomJsonRender,)
queryset = SomeModel.objects.all()
serializer_class = SomeSerializer

修改settings.py让修改全局生效

1
2
3
REST_FRAMEWORK = {
"DEFAULT_RENDERER_CLASSES": ("CustomJsonRender","rest_framework.renderers.BrowsableAPIRenderer"),
}

在这里还加入了一个DRF自带的BrowsableAPIRenderer,加入这个Renderer是为了使用DRF自带的WebApi管理界面,如果不加这个就只能得到json格式的数据,DRF自带的网页就看不到了

打赏

请我喝杯咖啡吧~

支付宝
微信