Django Response 知多少?
持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
序言
Django 是一个可以让人快速开发的框架,今天就来浅聊一下Django 接口返回的response。
大概分为几个点去进行:
- HttpResponse
- JsonResponse
- drf Response
- 自定义 drf Response
1. HttpResponse
django render 数据,返回template的时候,其实底层里面调用的就是HttpResponse。HttpResponse 通过自身定义的函数可以看出,它返回的response其实是string类型,然后传递的content是一个bytestring。
也就是如果定义返回的数据是json类型,那么在使用HttpResponse的时候,需要用json.dumps()去对数据进行转换。
然后在前端还需要对这数据进行解析,不然得到的数据其实是一个string类型。
其实,一般来说,对于接口的开发,这种需要前后端都对数据进行转换的,其实对于开发来说都是不怎么友好的,所以就有了JsonResponse.
使用验证
import json
from django.http import HttpRequest, JsonResponse, HttpResponse
def render_view(request: HttpRequest) -> HttpResponse:
return HttpResponse(content=json.dumps(dict(A=1, B=2)))
结果图:
2. JsonResponse
JsonResponse是继承于HttpResponse,然后在HttpResponse的基础上把数据序列化为JSON。它默认传递的数据得是字典类型的,如果不是会抛异常。
使用JsonResponse对于返回到前端的数据就是JSON类型,不需要前端开发同学对数据进行处理,这样子会比HttpResponse更利于开发。
但是这也有个不怎么爽快的点,就是在safe=True的时候,传递的数据必须是JSON类型,不然就报错。
对于实际开发来说,数据放回的格式其实有时候不一定是JSON,这样其实对类型限制也会部分限制了开发。
使用验证
from django.http import HttpRequest, JsonResponse, HttpResponse
def json_view(request: HttpRequest) -> JsonResponse:
return JsonResponse(data=dict(A=1, B=2))
结果图:
3. drf Response
一般来说,django经常会和drf搭配使用,当然这就不得不提起drf中的Response.它比起JsonResponse,并没有限制死数据的类型,也就是返回的数据可以是JSON,可以是字符串,可以是列表等等。
相对于JsonResponse,这个是很不错的点。
并且数据返回到前端的类型是和后端接口提供的类型一致的,并不会说返回到前端就变成字符串。
使用验证
from rest_framework.response import Response
from rest_framework.views import APIView
class TestView(APIView):
"""
drf Response
"""
def get(self, request, *args, **kwargs):
return Response(data=dict(A=1, B=2))
结果图:
4. 自定义 drf Response
其实对于接口开发来说,drf Response其实已经能满足80%的要求,但是开发接口的时候,返回的数据通常是会有类似这样子的格式ret = {
'msg': msg,
'status': code,
'data': data or {},
}
对于每个接口返回的格式都要类似这样子话,你不可能在每个接口Response 放回数据的时候,都按照这个格式一个一个这么写。
查阅drf文档,其实drf可以支持自定义drf Response.
这意味着自己自定义一个全局的drf Response,在里面定义好相应接口返回的数据格式,然后应用里面所有使用了drf Response的接口都会按照这个格式进行转换。
也就可以不用你每个接口都这么手写相同类似的字段,减少工作量。
那到底怎么去自定义drf Response呢?整理了一下,大概分为几个小点去进行:
- 写一个自定义的custom_response.py 文件
- 配置settings.py 文件里面的REST_FRAMEWORK 的 DEFAULT_RENDERER_CLASSES 配置custom_response中定义的返回格式
- 其他views.py 文件就正常引用Response,返回数据即可。
写一个自定义的custom_response.py 文件
from rest_framework.renderers import JSONRenderer
class RenderResponse(JSONRenderer):
# 重构render方法
def render(self, data, accepted_media_type=None, renderer_context=None):
if renderer_context:
code_default = 0 if renderer_context["response"].status_code == 200 else renderer_context[
"response"].status_code
# 如果返回的data为字典
if isinstance(data, dict):
# 响应信息中有message和code这两个key,则获取响应信息中的message和code,并且将原本data中的这两个key删除,放在自定义响应信息里
# 响应信息中没有则将msg内容改为请求成功 code改为请求的状态码
msg = data.pop('message', 'success')
code = data.pop('code', code_default)
# 如果不是字典则将msg内容改为请求成功 code改为请求的状态码
else:
msg = 'success'
code = code_default
# 自定义返回的格式
ret = {
'msg': msg,
'status': code,
'data': data or {},
}
# 返回JSON数据
return super().render(ret, accepted_media_type, renderer_context)
else:
return super().render(data, accepted_media_type, renderer_context)
配置settings.py 文件里面的REST_FRAMEWORK 的 DEFAULT_RENDERER_CLASSES
REST_FRAMEWORK = {
# 修改默认返回JSON的renderer的类
'DEFAULT_RENDERER_CLASSES': (
'utils.custom_response.RenderResponse',
),
}
其他views.py 文件就正常引用Response,返回数据即可
from rest_framework.response import Response
from rest_framework.views import APIView
class TestView(APIView):
"""
drf Response
"""
def get(self, request, *args, **kwargs):
return Response(data=dict(A=1, B=2))
结果图:
结语
截止到这里,该讲的已经讲完了,也希望这些东西能给人一点点作用,当然,文章不是完美的,有缺漏有错的也可以提出来,我也能进一步学习。最后,如果可以,点赞支持一波也行。