当前位置: 首页 > news >正文

Django REST framework--渲染器

Django REST framework--渲染器

    • Django REST framework--渲染器
      • 自定义接口规范
      • 渲染器基本原理
        • Django 项目debug调试技巧
      • 异常信息处理
        • 配置异常处理模块
        • 自定义异常处理

Django REST framework–渲染器

自定义接口规范

目前使用的是REST框架默认的返回格式,类似这种

[
    {
        "id": 38,
        "method": 0,
        "url": "/api/teacher/",
        "params": null,
        "headers": null,
        "cookies": null,
        "data": {
            "name": "小王老师",
            "courses": "英语",
            "address": "广东深圳"
        },
        "json": null,
        "step": null
    },
    {
        "id": 39,
        "method": 0,
        "url": "/api/teacher/",
        "params": null,
        "headers": null,
        "cookies": null,
        "data": {
            "name": "小王老师",
            "courses": "英语",
            "address": "广东深圳"
        },
        "json": null,
        "step": null
    }
]    

没有自定义响应字段封装,不利于前端的渲染和接口验证

希望接口在正确的时候返回

{"msg":"success","retcode":200,"retlist":[...]}

接口在错误的时候返回

{"msg":"error","retcode":404,"error":error_msg}

想要弄成类似这样的效果需要自定义DRF异常返回和自定义数据返回格式,在项目根目录下新增一个文件夹utils,在该文件夹下新建renderers.py文件并写入以下代码

from rest_framework.renderers import JSONRenderer

# 自定义渲染器
class MyRenderer(JSONRenderer):
    # 重构 render方法
    def render(self,data,accepted_media_type=None,renderer_context=None):
        # 响应状态码
        status_code = renderer_context['response'].status_code
        # 正常返回 status_code 以2开头
        if str(status_code).startswith('2'):
            res = {'msg':"success",'retcode':status_code,'retlist':data}
            # 返回父类方法
            return super().render(res,accepted_media_type,renderer_context)
        # 异常情况
        else:
            res = {'msg':"error",'retcode':status_code}
            return super().render(res,accepted_media_type,renderer_context)

settings.py文件底部添加DRF全局配置

# rest框架配置
REST_FRAMEWORK = {
    # 默认的渲染器
    'DEFAULT_RENDERER_CLASSES': (
        # 'rest_framework.renderers.JSONRenderer',
        # 'rest_framework.renderers.BrowsableAPIRenderer',
        'utils.renderers.MyRenderer',
 )
}

执行命令python manage.py runserver 0.0.0.0:8888启动项目,在浏览器中输入http://127.0.0.1:8888/requests/38,可以发现返回带响应字段的json数据

{
    "msg": "success",
    "retcode": 200,
    "retlist": {
        "id": 38,
        "method": 0,
        "url": "/api/teacher/",
        "params": null,
        "headers": null,
        "cookies": null,
        "data": {
            "name": "小王老师",
            "courses": "英语",
            "address": "广东深圳"
        },
        "json": null,
        "step": null
    }
}

在浏览器中输入不存在的id,返回失败,http://127.0.0.1:8888/requests/38,可以发现返回带异常字段的json数据

{"msg":"error","retcode":404}

若在浏览器中输入http://127.0.0.1:8888/requests/,则返回数据库中查询的所有数据,器json数据内容会放到以retlist为名的列表里

{
    "msg": "success",
    "retcode": 200,
    "retlist": [
        {
            "id": 38,
            "method": 0,
            "url": "/api/teacher/",
            "params": null,
            "headers": null,
            "cookies": null,
            "data": {
                "name": "小王老师",
                "courses": "英语",
                "address": "广东深圳"
            },
            "json": null,
            "step": null
        },
        {
            "id": 39,
            "method": 0,
            "url": "/api/teacher/",
            "params": null,
            "headers": null,
            "cookies": null,
            "data": {
                "name": "小王老师",
                "courses": "英语",
                "address": "广东深圳"
            },
            "json": null,
            "step": null
        }
    ]
}

渲染器基本原理

序列化在返回数据后并不是直接做为响应数据,而是经过渲染器的渲染,生成不同格式的响应内容,如html或json格式。REST本身支持HTML和json格式,有内置的渲染器。那么如果想要返回定制化的内容就要重写渲染器,按照指定的格式进行响应

在这里插入图片描述

重构渲染器就是重写父类渲染器的render方法,在renderers.py文件中,就是通过定义一个MyRenderer类来自定义渲染器,然后通过自定义render函数,来重写父类渲染器的render方法

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

自定义render函数中有 dataaccepted_media_typerenderer_context,其中accepted_media_typerenderer_context默认为None,也就是说这两个参数是可选的。

data指响应数据(序列化器的.data属性),等同于renderer_context[" response "].data的值

accepted_media_type是由内容协商阶段确定的所接受的媒体类型。根据客户端的 Accept: 头,这可能比渲染器的 media_type 属性更具体,可能包括媒体类型参数。例如 "application/json; nested=true"

renderer_context 是一个由view提供的上下文信息的字典。默认情况下这个字典会包括以下键: view , request , response , args , kwargs 。

  • renderer_context[" view "] 对应调用的视图函数

  • renderer_context[" request "] 对应本次请求对象,包含所有请求数据,如请求头,请求参数等等

  • renderer_context[" response "] 对应本次响应对象,包含所有响应数据,如响应头,状态码,响应数据

    等等

最后,通过super()将参数内容返回父类方法。

如果响应状态码status_code 以2开头,则说明响应成功,将{'msg':"success",'retcode':status_code,'retlist':data}作为data数据返回给父类方法;

如果响应状态码status_code 不以2开头,则说明响应失败,将{'msg':"error",'retcode':status_code}作为data数据返回给父类方法

Django 项目debug调试技巧

点击pycharm右上角,选中Edit Configurations,添加Django Server,编辑运行配置内容,应用成功后,点击调试按钮进行调试

在这里插入图片描述

return super().render(res,accepted_media_type,renderer_context)这行代码打上断点,然后在浏览器中输入http://127.0.0.1:8888/requests/38,通过pycharm查看debug控制台打印内容,了解数据的流转过程及数据内容

在这里插入图片描述

异常信息处理

当前情况下我们智能获取到正常情况下返回的数据,如果想返回异常信息,需要了解下REST异常处理机制,

REST默认情况可以处理的异常有:

  • 在REST framework内部产生的 APIException 的子类异常。

  • 原生Django的 Http404 异常.

  • 原生Django的 PermissionDenied 异常.

在这里插入图片描述

如果想要获取异常数据,需要从异常处理器中提取,REST默认的是 exception_handler,当触发异常时,获取到异常的响应信息,便可以自由定义其格式。

配置异常处理模块

settings.py文件底部添加DRF全局配置

# rest框架配置
REST_FRAMEWORK = {
   # 全局配置异常模块
   'EXCEPTION_HANDLER': 'utils.exception.my_exception_handler',
   # 默认的渲染器
   'DEFAULT_RENDERER_CLASSES': (
       'utils.renderers.MyRenderer',
   )
}

自定义异常处理

增加异常处理

utils文件夹下新建exception.py文件并写入以下代码

from rest_framework.views import exception_handler, Response


def my_exception_handler(exc, context):     # exc:异常信息   context:上下文
    # 首先调用REST framework默认的异常处理,以获得标准的错误响应。
    error_response = exception_handler(exc, context)
    if error_response:
        # 成功捕获到异常的情况
        error_response.data['msg'] = 'error'  # 标记
        error_response.data['retcode'] = error_response.status_code  # 状态码
        error_response.data['error'] = str(exc)  # 详细错误原因
        error_response.data.pop('detail')  # detail的异常信息比较简单
    return error_response

更新渲染器逻辑

from rest_framework.renderers import JSONRenderer

# 自定义渲染器
class MyRenderer(JSONRenderer):
    # 重构 render方法
    def render(self,data,accepted_media_type=None,renderer_context=None):
        # 默认把data作为响应数据
        resp_content = data
        if renderer_context:
            # 响应状态码
            status_code = renderer_context['response'].status_code
            # 正常返回 status_code 以2开头
            if str(status_code).startswith('2'):
                # 判断响应内容是否是列表形式,如果不是列表形式,则变成列表形式以对应接口要求
                if not isinstance(resp_content, list):
                    resp_content = [resp_content]
                res = {'msg':"success",'retcode':status_code,'retlist':data}
                # 返回父类方法
                return super().render(res,accepted_media_type,renderer_context)
            # 异常情况
            return super().render(resp_content,accepted_media_type,renderer_context)

相关文章:

  • 企业网站建设方案有那些/网络广告的类型有哪些
  • 云服务器可以做几个网站/中国免费网站服务器下载
  • 酒店网站建设功能/单页关键词优化费用
  • 网站换域名要怎么做/百度seo在哪里
  • wordpress采集插件推荐/软件网站排行榜
  • 渭南网站建设网站建设/太原网站建设方案咨询
  • JAVA面试(如何进行有效面试)
  • 拉伯证券|大股东或易主,阿里巴巴换股入局
  • JavaWeb-JavaScript
  • 一行代码加速Pytorch推理速度6倍
  • 二十一、迭代器模式 ( Iterator Pattern )
  • Zookeeper相关操作
  • 安科瑞电气火灾监控系统在春晓161#地块人防工程的设计与应用
  • DRR(Digitally Reconstructured Radiograph)分类及原理
  • 【Linux】创建新用户 sudo配置,添加信任
  • AI中Deepfake的部分研究前沿与文献综述
  • 矿场搭建(割点+找点联通分量)
  • K8S StatefulSet基本使用