Django REST framework--渲染器

news2024/11/29 20:43:57

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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/166054.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【redis6】第十章(事务和锁机制)

Redis的事务定义 Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。 Redis事务的主要作用就是串联多个命令防止别的命令插队。 Multi、Exec、discard 从输入Mu…

2023年面试题之Dubbo基础架构

一. Dubbo 的整体架构设计有哪些分层?接口服务层(Service):该层与业务逻辑相关,根据 provider 和 consumer 的业务设计对应的接口和实现配置层(Config):对外配置接口,以 ServiceCon…

Docker 应用实践-镜像篇

一个 Docker 镜像往往是由多个镜像层(可读层)叠加而成,每个层仅包含了前一层的差异部分,单个镜像层也往往可以看作镜像使用,当我们启动一个容器的时候,Docker 会加载镜像层并在其上添加一个可写层。容器上所…

C语言学习——字符函数和字符串函数

🌇个人主页:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html 小苏希望大家能从这篇文章中收获到许…

实战Kaggle比赛:预测房价

实战Kaggle比赛:预测房价 目录 下载和缓存数据集访问和读取数据集数据预处理训练K折交叉验证模型选择提交Kaggle预测 本节我们将通过Kaggle比赛,将所学知识付诸实践。 Kaggle的房价预测比赛是一个很好的起点。 此数据集由Bart de Cock于2011年收集 (D…

Linux--线程互斥与同步--0112 13

线程互斥 1.背景概念 临界资源:多线程执行流共享的资源就叫做临界资源。 临界区:每个线程内部,访问临界资源的代码就叫做临界区。 互斥:任何时刻,互斥保证有且只有一个执行流进入临界区 ,对临界资源起保…

36岁北邮硕士,四段大厂经历,当初为了涨薪频繁跳槽,被裁后投遍所有公司,基本都不回复!...

今天给大家分享一位36岁北邮硕士的职场经历:2013年北邮硕士毕业后,分别在乐视、字节、阿里、小米待过,2022年被小米裁员,几乎投遍了boss上所有公司,基本都是已读不回。只有一个小公司的hr看了简历后回了一句“加油”。…

绕过某博客查看文章验证码,关注公众号得验证码

之前也写过一篇,当时使用Burpsuite抓包,改包,有点杀鸡用牛刀了。 虽然我挺支持为知识那啥的,但是吧要我去关注公众号太麻烦了 绕过查看文章需要验证码 其实就是改一个返回的字段,既然后端也是改,那我前端…

Google Earth Engine基础使用方法(一)

Google Earth Engine 1、注册账号1.1、设置谷歌账号辅助邮箱1.2、进入Google Earth Engine(如果第一次注册失败怎么办)1.3、进入Google Earth Engine Editor2、Editor主界面2.1、上传自己的矢量数据2.2、分享代码给别人2.3、保存代码2.4、几个有效快捷键2.5、搜索框有什么用3、…

SAP S/4 FAGLGVTR错误解决

本次年结支持过程中,一个客户的年结操作出现问题,问题的解决还颇费周折,稍稍记录一下。客户的SAP 版本是 S/4, 通过 FAA_CMP 事务码切换固定资产年度的时候,提示上一已关闭的会计年度与当前会计年度相同。 这个消息的意思是FI 的会…

【自学Python】Python字符串出现次数

Python字符串出现次数 Python字符串出现次数教程 在开发过程中,很多时候我们有统计单个字符或者 字符串 在另一个字符串中出现次数的需求,在 Python 中,统计字符串出现次数我们使用 count() 函数。 Python count()函数详解 语法 S.count…

Python实战项目1——自动获取小说工具

🤵‍♂️ 个人主页老虎也淘气 个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏…

【C++】二叉树进阶OJ题

​🌠 作者:阿亮joy. 🎆专栏:《吃透西嘎嘎》 🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 目录👉根据二叉…

前端开发:Webpack的使用总结

前言 在前端开发过程中,尤其是现在前端框架的频繁使用的当下,作为前端开发者想必对于Webpack并不陌生,尤其是在使用Vue框架做前端开发的时候,打包时候必用Webpack。还有就是在前端求职面试的时候,Webpack相关的知识点…

mysql新建分区设置阈值(less than)引发的问题

mysql新建分表后,入库之前分表区间的数据,但是再分表中查询不到对应数据。 文章目录问题背景问题解析新建分区sql查看分区查询数据查询数据所在分区修改方案总结LESS THAN相关sql查询分区删除分区先建分区问题背景 初始化表的时候,先建的日期…

(二)Jenkins全局工具配置

目录 1、插件管理 2、Gitee安装 2.1、插件安装 2.2、查看Gitee状态 2.3、配置Gitee 2.4、获取私人令牌 2.5、测试连接 3、全局配置jdk、ant、maven 3.1、jdk配置 3.2、ant配置 3.3、maven配置 4、插件镜像下载地址配置 (一)Jenkins部署、基础配置介绍在windows下安…

事务(transaction)

事务(重点 五颗星 ***** 必须理解 必须掌握) 1、什么是事务: 一个事务其实就是一个完整的业务逻辑。 假设转账,从A账户向B账户转账10000.将A账户的钱减去10000(update语句),将B账 户的钱增加100…

【手写 Vue2.x 源码】第二十六篇 - 数组依赖收集的实现

一,前言 上篇,主要介绍了数组依赖收集的原理 本篇,数组依赖收集的实现 二,对象依赖收集的总结 {}.dep > watcher 目前,“对象本身”和“对象中的每一个属性”都拥有一个 dep 属性,用于做依赖收集 此…

Leetcode:669. 修剪二叉搜索树(C++)

目录 问题描述: 实现代码与解析: 递归: 原理思路: 后序递归: 原理思路: 迭代: 原理思路: 问题描述: 给你二叉搜索树的根节点 root ,同时给定最小边界…

#9文献学习--基于元强化学习的边缘计算快速自适应任务卸载

文献:Fast Adaptive Task Offloading in Edge Computing based on Meta Reinforcement Learning 基于深度强化学习DRL的方法,样本效率很低,需要充分的再培训来学习新环境的更新策略,对新环境的适应性很弱。 基于元强化学习的任务…