Django一分钟:在Django中怎么存储树形结构的数据,DRF校验递归嵌套模型的替代方案

引言

在开发过程中我们可能需要这样的树形结构:

[{"data": {"name": "牛奶"},"children": [{"data": {"name": "蒙牛"}, },{"data": {"name": "伊利"}, }]},{"data": {"name": "面包"},"children": [{"data": {"name": "黑面包"}, },{"data": {"name": "白面包"}, }]}
]

这种需求很常见,比如:分层的用户组、产品组件表等等,你都会用到树形结构,为这样的需求在django中自己从头创建模型并实现一系列的API是一个相当大的工作,好在我们有很多现成的库可以使用。

如果你在想:Django能不能做到某件事情;来这个网站看看是个好习惯。

一、创建和使用模型

本文中我们用到的库是django-treebeard

pip install django-treebeard

django-treebeard提供了三种实现方式:邻接表、嵌套集、路径树(MPTT)。下面我们使用路径树来演示,创建模型如下:

class Category(MP_Node):name = models.CharField(max_length=30)node_order_by = ['name']def __str__(self):return 'Category: {}'.format(self.name)

路径树会为你额外创建三个字段来辅助定义结构分别是pathdepthnumchild,它的插入和更新等维护比较繁重,但查询速度相当快。本文中我们不具体讨论实现原理,只是做简单使用演示,并为你可能遇到的问题提供思路,想详细了解其所有API阅读其文档。

定义好模型之后,模型中的一些方法可以辅助我们完成序列化和反序列化,快速的在数据库中保存和拉取数据:

>>> data =[{# tree1"data": {"name": "牛奶"},"children": [{"data": {"name": "蒙牛"}, },{"data": {"name": "伊利"}, }]},{# tree2"data": {"name": "面包"},"children": [{"data": {"name": "黑面包"}, },{"data": {"name": "白面包"}, }]}
]
>>> Category.load_bulk(data)
>>> Category.dump_bulk()
# [{'data': {'name': '牛奶'}, 'id': 1, 'children': [{'data': {'name': '伊利'}, 'id': 3}, {'data': {'name': '蒙牛'}, 'id': 2}]}, {'data': {'name': '面包'}, 'id': 4, 'children': [{'data': {'name': '白面包'}, 'id': 6}, {'data': {'name': '黑面包'}, 'id': 5}]}]

二、数据校验

假如你使用django rest framework为这样的递归嵌套的模型创建序列化器非常的困难,我推荐的解决方法是使用pydantic,如果你学习过FastAPI框架你应该对它不陌生。pydantic无法从django模型中自动生成模型,你需要自己定义:

from pydantic import BaseModelclass CategoryNodelModel(BaseModel):name: strclass CategoryTreeModel(BaseModel):data: CategoryNodelModelchildren: list['CategoryTreeModel'] | None = None

使用方法:

# 假设用户输入
>>> data = [{# tree1"data": {"name": "牛奶"},"children": [{"data": {"name": "蒙牛"}, },{"data": {"name": "伊利"}, }]},{# tree2"data": {"name": "面包"},"children": [{"data": {"name": "黑面包"}, },{"data": {"name": "白面包"}, }]}
]
# 测试用户输入的结构是否正确
>>> [CategoryTreeModel(**tree) for tree in data]
# 保存到数据库
>>> Category.load_bulk(data)

下面是测试代码,包含对一些api的简单演示:

from rest_framework.test import APITestCase
from api.models import Category
from api.views import CategoryS, CategoryNodelModel, CategoryTreeModelclass TestCategory(APITestCase):def setUp(self):# 用户输入data = [{# tree1"data": {"name": "牛奶"},"children": [{"data": {"name": "蒙牛"}, },{"data": {"name": "伊利"}, }]},{# tree2"data": {"name": "面包"},"children": [{"data": {"name": "黑面包"}, },{"data": {"name": "白面包"}, }]}]# 测试用户输入的结构是否正确[CategoryTreeModel(**tree) for tree in data]Category.load_bulk(data)def test_get_all(self):print(Category.dump_bulk())def test_get_tree(self):milk = Category.objects.filter(name='牛奶').first()if milk:print(Category.dump_bulk(milk))def test_delete(self):milk = Category.objects.filter(name='面包').first()milk.delete()print(Category.dump_bulk())

总结

对于在django中使用树、图等复杂结构之类需求,可以去尝试寻找现成的库;对于复杂数据的校验可以尝试使用pydantic。选择合适的工具会为我们节省很多时间。

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

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

相关文章

为什么e^x的导数是本身

参考Why is the derivative of exex?的解法如下。 主要是利用导数的定义,将 f ′ ( x ) f(x) f′(x)转化为另一个公式,其值为1。 lim ⁡ h → 0 e h − 1 h \lim_{h \to 0} \frac{e^h - 1}{h} h→0lim​heh−1​ 而如何求这个公式的值?有人…

【论文速看】DL最新进展20241005-Transformer、目标跟踪、Diffusion Transformer

目录 【Transformer】【目标跟踪】【Diffusion Transformer】 【Transformer】 [NeurlPS 2024] Parameter-Inverted Image Pyramid Networks 机构:清华大学、上海AI Lab、上交、港中文、商汤 论文链接:https://arxiv.org/pdf/2406.04330 代码链接&…

【文献阅读】Attention Bottlenecks for Multimodal Fusion

Abstract 在多模态视频分类中,将各模态的最终表示或预测进行后期融合(“后期融合”)仍然是主流范式。为此,本文提出了一种基于 Transformer 的新型架构,该架构使用“融合瓶颈”在多个层次进行模态融合。与传统的成对自…

D28【python 接口自动化学习】- python基础之输入输出与文件操作

day28 输入 学习日期:20241005 学习目标:输入输出与文件操作﹣-40 输入:如何接收用户通过键盘输入的数据? 学习笔记: 输入设备与输入方式 Input函数 命令行参数 可选参数 必填参数 强制转换参数类型 总…

Linux环境搭建git服务器和代码自动化部署

在开发过程中,我们经常遇到的问题就是提交代码到测试地址,然后进行线上测试。 要实现Git代码的自动化部署,考虑以下几种方法 FTP提交:可以使用FTP将代码上传到服务器自动化部署工具:如Jenkins、当代码被推送到仓库时…

【Kubernetes】常见面试题汇总(五十五)

目录 121. POD 创建失败? 122. POD 的 ready 状态未进入? 特别说明: 题目 1-68 属于【Kubernetes】的常规概念题,即 “ 汇总(一)~(二十二)” 。 题目 69-113 属于【Kube…

Java项目实战II基于Java+Spring Boot+MySQL的宠物咖啡馆平台的设计与实现(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者 一、前言 在快节奏的城市生活中,宠物咖啡馆作为一种结合了休闲与宠物陪伴的新型业态,正…

重学SpringBoot3-集成Redis(三)

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ 重学SpringBoot3-集成Redis(三) 1. 引入 Redis 依赖2. 配置 RedisCacheManager 及自定义过期策略2.1 示例代码:自定义过期策略 3. 配置…

I/O多路转接

目录 一、select 1.1、select概念 1.2、select 函数原型 1.3、理解 select 执行过程 1.4、select就绪条件 1.4.1、读就绪 1.4.2、写就绪 1.4.3、异常就绪(了解) 1.5、select 基本工作流程 1.6、select服务器 1.6.1、Sock.hpp 1.6.2、selectS…

【复习】html最重要的表单和上传标签

文章目录 imgforminput img <img src"https://tse1-mm.cn.bing.net/th/id/OIP-C._XVJ53-pN6sDMXp8W19F4AAAAA?rs1&pidImgDetMain"alt"二次元"height"350px"width"200px"/>常用 没啥说的&#xff0c;一般操作css多一些 for…

CSP-J/S复赛算法 动态规划初步

文章目录 前言动态规划动态规划常见形式动态规划求最值的几个例子1. **背包问题**2. **最短路径问题**3. **最小硬币找零问题**4. **最长递增子序列** 总结 最优子结构举个简单的例子其他例子条件 DP的核心就是穷举具体解释 递归的算法时间复杂度dp数组的迭代解法通俗易懂的解释…

LabVIEW提高开发效率技巧----使用动态事件

在LabVIEW开发过程中&#xff0c;用户交互行为可能是多样且不可预知的。为应对这些变化&#xff0c;使用动态事件是一种有效的策略。本文将从多个角度详细介绍动态事件的概念及其在LabVIEW开发中的应用技巧&#xff0c;并结合实际案例&#xff0c;说明如何通过动态事件提高程序…

招联2025校招内推倒计时

【投递方式】 直接扫下方二维码&#xff0c;或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus&#xff0c;使用内推码 igcefb 投递&#xff09; 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…

8648 图的深度遍历

### 思路 1. **图的邻接表存储结构**&#xff1a;使用邻接表存储图的顶点和边信息。 2. **基本操作函数**&#xff1a;包括创建图、查找顶点、获取顶点值、获取第一个邻接顶点、获取下一个邻接顶点等。 3. **深度优先遍历&#xff08;DFS&#xff09;**&#xff1a;从某个顶点出…

车载项目:HIL测试、功能安全测试、CAN一致性测试、UDS测试、ECU测试、OTA测试、TBOX测试、导航测试、车控测试

FOTA模块中OTA的知识点&#xff1a;1.测试过程中发现哪几类问题&#xff1f; 可能就是一个单键的ecu&#xff0c;比如升了一个门的ecu&#xff0c;他的升了之后就关不上&#xff0c;还有就是升级组合ecu的时候&#xff0c;c屏上不显示进度条。 2.在做ota测试的过程中&#xff…

今日指数项目个股描述功能实现

个股描述功能实现 1 个股描述功能实现说明 1&#xff09;原型示意 2&#xff09;接口说明 功能描述&#xff1a;个股主营业务查询接口 服务路径&#xff1a;/api/quot/stock/describe 服务方法&#xff1a;GET 请求参数&#xff1a;code #股票编码 响应参数&#xff1a; {…

java计算机毕设课设—坦克大战游戏

这是什么系统&#xff1f; 坦克大战游戏是一款以坦克为主题的射击游戏&#xff0c;旨在为玩家提供一个刺激、有趣的游戏体验。该游戏不仅拥有丰富的功能&#xff0c;还注重玩家的互动体验。此系统是使用Java语言实现坦克大战游戏程序&#xff0c;玩家通过连接访问进入游戏&…

C语言指针plus版练习

上期我们讲了进阶的指针&#xff0c;本期内容我们来强化一下上期学的内容 一、字符串左旋 实现一个函数&#xff0c;可以左旋字符串中的k个字符。 1.1 分析题目 假设字符串为abcde&#xff0c;左旋一个以后就变成bcdea&#xff0c;就是把第一个字符移到一个新的变量里面&#…

一、走进新语言

走进新语言 介绍环境配置JDK配置Kotlin配置 开发工具代码基本结构程序注释 介绍 Kotlin是一种现代但已经成熟的编程语言&#xff0c;旨在让开发人员更快乐。它简洁、安全、可与Java和其他语言互操作&#xff0c;并提供了许多在多个平台之间重用代码的方法。它由JetBrains公司于…

8647 实现图的存储结构

### 思路 1. 读取输入的顶点个数n和边的条数m。 2. 初始化一个n*n的邻接矩阵&#xff0c;所有元素初始为0。 3. 读取每条边的信息&#xff0c;更新邻接矩阵对应位置为1。 4. 输出邻接矩阵。 ### 伪代码 1. 读取n和m。 2. 初始化n*n的邻接矩阵matrix&#xff0c;所有元素为0。 …