Wrapping Django API Responses in a Unified Format
Introduction I've been really busy lately. I started a new project, and to get a product out quickly I chose Django for the backend, then picked up the project scaffolding I had packaged before, DjangoStarter. Because I wrote quite a bit of .NetCore backend code recently and gained some new insights into CRUD API development, I definitely have to revamp DjangoStarter as well, to make it more convenient to use~ Side note: I finally actually started using react on the frontend. I have to say ts + react is really nice to use,
目录5 个章节
Introduction
I've been really busy lately. I started a new project, and to get a product out quickly I chose Django for the backend, then picked up the project scaffolding I had packaged before, DjangoStarter.
Because I wrote quite a bit of .NetCore backend code recently and gained some new insights into CRUD API development, I definitely have to revamp DjangoStarter as well, to make it more convenient to use~
Side note: I finally actually started using react on the frontend. I have to say ts + react is really nice to use. The recommendation from "Frontend Guru" was really solid (nice
The Main Topic
To be precise, this is implemented together with DjangoRestFramework. The core code consists of two parts: one is the error-handling wrapper, and the other is the response wrapper renderer.
Whether the request errors or not, it will be wrapped by our custom renderer.
Code
Let's get to the code~
First, add a new Python package to the project. Place it wherever makes sense for you; in the DjangoStarter template, I put it at utils/response. The next two files will both go in this directory.
The first is the error-handling exception.py file:
from typing import Dict
from rest_framework.exceptions import ValidationError
from rest_framework.views import exception_handler
from rest_framework.views import Response
from rest_framework.utils.serializer_helpers import ReturnDict
from rest_framework import status
def custom_handler(err: ValidationError, context: dict):
# 先调用REST framework默认的异常处理方法获得标准错误响应对象
response: Response = exception_handler(err, context)
if response is None:
return Response({
'message': f'服务器错误:{err}'
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=True)
else:
# 因为RestFramework默认的报错信息是 detail 字段,这里取出系统的报错信息
msg = response.data.pop('detail', response.reason_phrase)
res = {'message': msg}
res.update(response.data)
return Response(res, status=response.status_code, exception=True)
Then the custom renderer.py code:
from rest_framework.renderers import JSONRenderer
class CustomRenderer(JSONRenderer):
# 重构render方法
def render(self, data, accepted_media_type=None, renderer_context=None):
if renderer_context:
# 响应的信息,成功和错误的都是这个
# 成功和异常响应的信息,异常信息在前面自定义异常处理中已经处理为{'message': 'error'}这种格式
# 如果返回的data为字典
if isinstance(data, dict):
# 响应信息中有message和code这两个key,则获取响应信息中的message和code,并且将原本data中的这两个key删除,放在自定义响应信息里
# 响应信息中没有则将msg内容改为请求成功 code改为请求的状态码
msg = data.pop('message', '请求成功')
code = data.pop('code', renderer_context["response"].status_code)
# 如果不是字典则将msg内容改为请求成功 code改为响应的状态码
else:
msg = '请求成功'
code = renderer_context["response"].status_code
# 自定义返回的格式
ret = {
'message': msg,
'code': code,
'data': data,
}
# 返回JSON数据
return super().render(ret, accepted_media_type, renderer_context)
else:
return super().render(data, accepted_media_type, renderer_context)
The key parts are commented, so it should be easy to follow.
After wrapping, every API's return value looks like this:
{
"message": "msg",
"code": 200,
"data": {
"data1": "123"
}
}
Configuration
For the code above to take effect, you still need to configure RestFramework.
Edit the settings.py file and add these two settings under the REST_FRAMEWORK node. Make sure the paths match the two files above. Here I'm using the DjangoStarter project as an example.
REST_FRAMEWORK = {
# 全局配置异常模块
'EXCEPTION_HANDLER': 'utils.response.exception.custom_handler',
# 修改默认返回JSON的renderer的类
'DEFAULT_RENDERER_CLASSES': ('utils.response.renderer.CustomRenderer',),
}
That's it~ It's that simple.
(Simpler than wrapping return values in AspNetCore……)
The full code is available on GitHub: https://github.com/Deali-Axy/DjangoStarter
References
- Customizing Django REST framework response data format: https://blog.csdn.net/qq_41475058/article/details/112676908
_EOF_
Wrapping Django API Responses in a Unified Format
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
Django中「强行」使用MVVM设计模式
扫盲 首先带大家了解一下什么是MVVM模式: 什么是MVVM?MVVM是Model-View-ViewModel的缩写。 MVVM是MVC的增强版,实质上和MVC没有本质区别,只是代码的位置变动而已 从名字上看,MVVM比MVC架构中多了一个ViewModel,没错,就是这个ViewModel,他是MVVM相对于MVC改进的核心思想。在开发过程中,由于需求的变更或添加,项目的复杂度越来越高,代码量
2021-12-18 · Django · 约 1 分钟
使用django-treebeard实现树类型存储与编辑
无非继承MP_Node配置TreeAdmin,拖拽编辑树节点。可视化?也就django-treebeard能用,其他要么停更要么功能拉胯。初始化数据?手动导入,否则admin连按钮都没有,bug。接口输出无非path和depth,自己实现更舒服。
2024-08-11 · Django · 约 1 分钟
Django-Import-Export插件控制数据导入流程
前言 之前写过两篇跟这个插件有关的文章,可以回顾一下: Django数据导入导出神器django-import-export使用 Django-Import-Export插件关于外键的处理 最近有个朋友留言问我一个关于django-import-export插件的问题 为了形象表达这个问题,我举个书籍管理的例子来描述一下 数据库表 | id | name | price | | ---- |
2022-09-02 · Django · 约 1 分钟
使用easy_thumbnails轻松为图片创建缩略图
关于Django的缩略图 我在Django的官方文档里看了一下,没有找到有关缩略图的官方库,不过在Django的Wiki里头倒是看到了一篇关于使用缩略图的介绍,请参考:https://code.djangoproject.com/wiki/ThumbNails 关于Problem的描述 The majority of applications that have images, probably
2022-08-26 · Django · 约 1 分钟
讨论
共 0 条加载评论中…