教程总体简介:项目概述 项目背景 项目的功能构架 项目的技术架构 CMS 什么是CMS CMS需求分析与工程搭建 静态门户工程搭建 SSI服务端包含技术 页面预览开发 4 添加“页面预览”链接 页面发布 需求分析 技术方案 测试 环境搭建 数据字典 服务端 前端 数据模型 页面原型 前端页面 上传图片开发 前端开发 图片查询 静态页面测试 CMS页面预览测试 CMS添加页面接口 搜索服务 搭建ES环境 后端工程搭建 导入CMS数据库 MongoEngine入门 在Django中使用MongoDB 定义文档 Logstash创建索引 创建搜索应用 定义ESClient 搜索前端技术需求 了解SEO 服务端渲染和客户端渲染 Nuxt.js入门 创建Nuxt工程 页面布局 路由 获取数据 搜索页面 查询全部 分页查询 按分类搜索 按难度等级搜索 集成测试 在线学习与媒资管理 在线学习需求分析 需求描述 视频点播解决方案 视频编码 FFmpeg的基本使用 生成m3u8/ts文件 播放器 搭建学习中心前端 媒资管理 开发环境 上传文件 断点续传解决方案 文件分块与合并 媒资服务端编写 视频处理 发送视频处理消息 我的媒资 选择视频 保存视频信息 Api接口 学习页面获取视频播放地址 在线学习接口 登录注册与认证授权 增加数据 修改数据 删除数据 查询数据 Q对象 其他 查询集 QuerySet 页面管理后端开发 接口说明 接口开发规范 JWT Django REST framework JWT 用户登录前端 前端显示当前用户 用户退出 前端集成认证授权 用户注册后端 订单与选课 分布式事务 问题描述 CAP理论 解决方案 自动添加选课方案 Celery Beat定时任务 订单服务定时发送消息 查询前N条任务 乐观锁取任务 RabbitMQ配置 学习服务添加选课 订单服务结束任务 传智云课堂 封装异常处理 封装JSON返回值 站点列表和模板列表接口 新增页面 页面查询接口定义 自定义条件查询 3 测试接口 页面详情 修改页面 删除页面 CMS前端工程创建 导入系统管理前端工程 单页面应用介绍 CMS前端页面查询开发 创建页面 Table组件测试 页面内容完善 跨域问题解决 进入页面立即查询 前后端请求响应流程小结 新增页面前端开发 页面处理流程 页面静态化及预览发布 页面静态化需求 模板管理 模板管理业务流程 模板制作 GridFS研究 模板存储
完整笔记资料代码:https://gitee.com/yinuo112/Backend/tree/master/Python/嘿马云...
感兴趣的小伙伴可以自取哦~
全套教程部分目录:
部分文件图片:
封装异常处理
学习目标
- 掌握统一异常处理封装的方法
1 接口异常返回
在BookInfoViewSet视图集中模拟接口异常:
from rest_framework.exceptions import APIException
class BookInfoViewSet(ModelViewSet):
...
def list(self, request, *args, **kwargs):
raise APIException('请求出错!')
return super().list(request, *args, **kwargs)
访问 [ 接口报错信息如下:
2 定义返回信息
我们将success、code、message封装到元组中,放到一个单独的文件中统一管理。
思考:有没有其他的数据结构来封装这些信息(namedtuple)?
新建common/response_code.py,添加我们系统用到的响应信息如下:
SUCCESS = (True, 10000, "操作成功!")
FAIL = (False, 11111, "操作失败!")
UNAUTHENTICATED = (False, 10001, "此操作需要登陆系统!")
UNAUTHORISE = (False, 10002, "权限不足,无权操作!")
INVALID_PARAM = (False, 10003, "非法参数!")
SERVER_ERROR = (False, 99999, "抱歉,系统繁忙,请稍后重试!")
UPLOAD_FILE_REGISTER_FAIL = (False, 22001, "上传文件在系统注册失败,请刷新页面重试!")
UPLOAD_FILE_REGISTER_EXIST = (False, 22002, "上传文件在系统已存在!")
CHUNK_FILE_EXIST_CHECK = (False, 22003, "分块文件在系统已存在!")
MERGE_FILE_FAIL = (False, 22004, "合并文件失败,文件在系统已存在!")
MERGE_FILE_CHECKFAIL = (False, 22005, "合并文件校验失败!")
AUTH_USERNAME_NONE = (False, 23001, "请输入账号!")
AUTH_PASSWORD_NONE = (False, 23002, "请输入密码!")
AUTH_VERIFYCODE_NONE = (False, 23003, "请输入验证码!")
AUTH_ACCOUNT_NOTEXISTS = (False, 23004, "账号不存在!")
AUTH_CREDENTIAL_ERROR = (False, 23005, "账号或密码错误!")
AUTH_LOGIN_ERROR = (False, 23006, "登陆过程出现异常请尝试重新操作!")
CMS_ADDPAGE_EXISTSNAME = (False, 24001, "页面名称已存在!")
CMS_ADDPAGE_EXISTS = (False, 24002, "页面已存在!")
CMS_GENERATEHTML_DATAURLISNULL = (False, 24003, "从页面信息中找不到获取数据的url!")
CMS_GENERATEHTML_DATAISNULL = (False, 24004, "根据页面的数据url获取不到数据!")
CMS_GENERATEHTML_TEMPLATEISNULL = (False, 24005, "页面模板为空!")
CMS_GENERATEHTML_HTMLISNULL = (False, 24006, "生成的静态html为空!")
CMS_GENERATEHTML_SAVEHTMLERROR = (False, 24007, "保存静态html出错!")
CMS_PAGE_NOTEXISTS = (False, 24008, "页面不存在!")
CMS_COURSE_PERVIEWISNULL = (False, 24009, "预览页面为空!")
FS_UPLOADFILE_FILEISNULL = (False, 25001, "上传文件为空!")
FS_UPLOADFILE_BUSINESSISNULL = (False, 25002, "业务Id为空!")
FS_UPLOADFILE_SERVERFAIL = (False, 25003, "上传文件服务器失败!")
FS_DELETEFILE_NOTEXISTS = (False, 25004, "删除的文件不存在!")
FS_DELETEFILE_DBFAIL = (False, 25005, "删除文件信息失败!")
FS_DELETEFILE_SERVERFAIL = (False, 25006, "删除文件失败!")
FS_UPLOADFILE_METAERROR = (False, 25007, "上传文件的元信息请使用json格式!")
FS_UPLOADFILE_USERISNULL = (False, 25008, "上传文件用户为空!")
COURSE_NOTEXISTS = (False, 30001, "不存在")
COURSE_DENIED_DELETE = (False, 31001, "删除失败,只允许删除本机构的!")
COURSE_PUBLISH_PERVIEWISNULL = (False, 31002, "还没有进行预览!")
COURSE_PUBLISH_CDETAILERROR = (False, 31003, "创建详情页面出错!")
COURSE_PUBLISH_COURSEIDISNULL = (False, 31004, "Id为空!")
COURSE_PUBLISH_VIEWERROR = (False, 31005, "发布视图出错!")
COURSE_PUBLISH_CREATECOURSEPUB_ERROR = (False, 31006, "创建索引信息出错!"),
COURSE_TEACHPLAN_EXIST = (False, 31050, "已经绑定教学计划")
COURSE_TEACHPLAN_NOTEXISTS = (False, 31051, "计划不存在")
COURSE_MEDIS_URLISNULL = (False, 31101, "选择的媒资文件访问地址为空!")
COURSE_MEDIS_NAMEISNULL = (False, 31102, "选择的媒资文件名称为空!")
COURSE_MEDIA_TEACHPLAN_GRADEERROR = (False, 31104, "只允许选择第三级的计划关联视频!")
COURSE_PIC_NOTEXISTS = (False, 31201, "未找到图片!")
COURSE_PIC_UPLOAD_ERROR = (False, 31202, "图片上传失败!")
ORDER_ADD_ITEMISNULL = (False, 41001, "创建订单未选择!")
ORDER_ADD_ORDERNUMERROR = (False, 41002, "生成订单号错误!")
ORDER_ADD_GETCOURSEERROR = (False, 41003, "找不到信息!")
ORDER_FINISH_NOTFOUNDORDER = (False, 41004, "找不到订单信息!")
Pay_NOTFOUNDORDER = (False, 41010, "找不到要支付的订单!")
Pay_USERERROR = (False, 41011, "支付用户与订单用户不一致!")
Pay_NOTFOUNDPAY = (False, 41012, "支付记录不存在!")
COURSE_COMMENT_EXISTS = (False, 41031, "已评价!")
PortalView_ADDVIEWCOURSE_COURSEIDISNULL = (False, 42001, "id为空!")
PortalView_PUBLISH_PREVIEWCOURSE_ISNULL = (False, 42002, "预览视图为空!")
PortalView_PUBLISH_PREVIEWMEDIA_ISNULL = (False, 42003, "预览媒资视图为空!")
3 定制通用错误处理
要将对应的响应信息返回,我们采用定制exception_handler的方式
定义API异常类(common/exceptions.py)
from rest_framework.exceptions import APIException
class MyAPIException(APIException):
"""
封装自己的异常处理类,用于返回标准异常信息
"""
def __init__(self, detail=None, code=None):
# 判断detail是否符合标准异常信息的格式
if isinstance(detail, tuple) and len(detail) == 3:
# 保存标准异常信息
self._error_response = detail
detail = self.default_detail
if code is None:
code = self.default_code
super().__init__(detail=detail, code=code)
# 封装方法获取异常代码信息
def get_error_response(self):
return self._error_response
定义异常处理函数(common/exceptions.py)
from rest_framework.views import exception_handler
from common.response_code import SERVER_ERROR
def standard_exception_handler(exc, context):
"""
封装自己的异常处理函数,用于处理抛出的标准异常信息
"""
response = exception_handler(exc, context)
if isinstance(exc, APIException):
if isinstance(exc, MyAPIException):
# 获取标准异常信息中的数据,并组装返回数据
success, code, message = exc.get_error_response()
data = {'success': success, 'code': code, 'message': message, 'data': {}}
else:
data = {'success': SERVER_ERROR[0], 'code': SERVER_ERROR[1], 'message': exc.detail, 'data': {}}
response.data = data
response.status_code = 200
return response
简单封装一个异常抛出函数(common/exceptions.py)
def cast_exception(code):
"""
封装异常抛出函数,方便后期修改
"""
raise MyAPIException(code)
在cz_study/settings.py中配置异常处理函数
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'common.exceptions.standard_exception_handler',
}
4 测试接口异常返回
修改BookInfoViewSet视图集中的接口异常代码:
from common import exceptions, response_code
class BookInfoViewSet(ModelViewSet):
...
def list(self, request, *args, **kwargs):
exceptions.cast_exception(response_code.FAIL)
return super().list(request, *args, **kwargs)
再次访问 [ ,接口返回数据如下:
5 小结
封装异常处理
- 定义返回信息:我们将success、code、message封装到元组中,放到一个单独的文件中统一管理
- 定义API异常类:将元组信息保存到异常对象中
- 定义异常处理函数:使用异常处理函数取出异常信息,并生成response
- 封装统一的异常抛出函数:统一管理,统一修改
封装JSON返回值
学习目标
- 掌握自定义drf中renderer的方法
1 回顾接口正常返回
去掉报错代码, [ 接口的返回值如下:
2 定制JSONRenderer
要将JSON返回封装成约定的格式,可以定制JSONRenderer。
新建common/renderers.py
from rest_framework.renderers import JSONRenderer
from common.response_code import SUCCESS
class StandardJSONRenderer(JSONRenderer):
def render(self, data, accepted_media_type=None, renderer_context=None):
data = {} if data is None else data
if isinstance(data, dict) and data.get('success') is not None:
standard_data = data
else:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。