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

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。选择合适的工具会为我们节省很多时间。

相关文章:

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

引言 在开发过程中我们可能需要这样的树形结构: [{"data": {"name": "牛奶"},"children": [{"data": {"name": "蒙牛"}, },{"data": {"name": "伊利"}, }]},{"da…...

【Docker从入门到进阶】06.常见问题与解决方案 07.总结与资源

6. 常见问题与解决方案 在使用Docker进行开发和部署过程中,可能会遇到各种问题。以下是一些常见问题及其解决方案: 容器启动失败和调试 在使用 Docker 时,容器启动失败或立即退出可能会导致一定的困扰,以下是进一步深入解决该问…...

快速排序的非递归实现:借助栈实现、借助队列实现

目录 用栈实现快速排序 1.用栈实现非递归快速排序的思路步骤 1.1.思路步骤 2.用栈实现非递归快速排序的代码 3.用栈实现非递归快速排序的整个工程 3.1.QuickSortNonR.h 3.2.QuickSortNonR.c 3.3.Stack.h 3.4.Stack.c 用队列实现非递归快速排序 1.用队列实现非递归快…...

Finops成本优化企业实践-可视化篇

引言:上一章讨论了finops的一些方法论,笔者在拿到finops官方认证finops-engineer certificate之后,将方法论运用到所在项目组中,并于今年完成了40%的费用节省。在此将这些实践方法总结沉淀,与大家分享。实践包括三篇&a…...

Spring Boot中线程池使用

说明:在一些场景,如导入数据,批量插入数据库,使用常规方法,需要等待较长时间,而使用线程池可以提高效率。本文介绍如何在Spring Boot中使用线程池来批量插入数据。 搭建环境 首先,创建一个Spr…...

Python机器学习:自然语言处理、计算机视觉与强化学习

📘 Python机器学习:自然语言处理、计算机视觉与强化学习 目录 ✨ 自然语言处理(NLP) 文本预处理:分词、去停用词词向量与文本分类:使用Word2Vec与BERT 🌆 计算机视觉基础 图像预处理与增强目标…...

Vue2 + ElementUI + axios + VueRouter入门

之前没有pc端开发基础,工作需要使用若依框架进行了一年的前端开发.最近看到一个视频框架一步步集成,感觉颇受启发,在此记录一下学习心得。视频链接:vue2element ui 快速入门 环境搭建和依赖安装 安装nodejs安装Vue Cli使用vue create proje…...

GO网络编程(四):海量用户通信系统2:登录功能核心【重难点】

目录 一、C/S详细通信流程图二、消息类型定义与json标签1. 消息类型定义2. JSON标签3.结构体示例及其 JSON 表示:4.完整代码与使用说明 三、客户端发送消息1. 连接到服务器2. 准备发送消息3. 创建 LoginMes 并序列化4. 将序列化后的数据嵌入消息结构5. 序列化整个 M…...

某项目实战分析代码二

某项目实战分析代码二 此次分析的是protobuf的使用操作流程具体实现 3. 业务数据分析3.1 客户端3.2 服务器端简单案例 此次分析的是protobuf的使用 Protocol Buffer( 简称 Protobuf) 是Google公司内部的混合语言数据标准,它是一种轻便高效的结构化数据存储格式&…...

全面指南:探索并实施解决Windows系统中“mfc140u.dll丢失”的解决方法

当你的电脑出现mfc140u.dll丢失的问题是什么情况呢?mfc140u.dll文件依赖了什么?mfc140u.dll丢失会导致电脑出现什么情况?今天这篇文章就和大家聊聊mfc140u.dll丢失的解决办法。希望能够有效的帮助你解决这问题。 哪些程序依赖mfc140u.dll文件…...

QT学习笔记1(QT和QT creator介绍)

QT学习笔记1(QT和QT creator介绍) Qt 是一个跨平台的应用开发框架,主要用于图形用户界面(GUI)应用的开发,但也支持非GUI程序的开发。Qt 支持多种平台,如Windows、macOS、Linux、iOS和Android&a…...

存储电话号码的数据类型,用 int 还是用 string?

在 Java 编程中,存储电话号码的选择可以通过两种常见方式进行:使用 int 类型或 String 类型。这种选择看似简单,但实际上涉及到 JVM 内部的字节码实现、内存优化、数据表示、以及潜在的可扩展性问题。 Java 基本数据类型与引用数据类型的差异…...

【目标检测】工程机械车辆数据集2690张4类VOC+YOLO格式

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2694 标注数量(xml文件个数):2694 标注数量(txt文件个数):2694 标注…...

target_link_libraries()

target_link_libraries() 是 CMake 中的一个命令,用于指定目标(如可执行文件或库)所依赖的其他库。其主要作用包括: 链接库:将指定的库链接到目标上,使目标能够调用这些库中的函数和使用其功能。 管理依赖…...

Javascript数组研究09_Array.prototype[Symbol.unscopables]

Symbol.unscopables 是 JavaScript 中一个相对较新的符号(Symbol),用于控制对象属性在 with 语句中的可见性。它主要用于内置对象,如 Array.prototype,以防止某些方法被引入到 with 语句的作用域中,避免潜在…...

SkyWalking 自定义链路追踪

对项目中的业务方法&#xff0c;实现链路追踪&#xff0c;方便我们排查问题 引入依赖 <!‐‐ SkyWalking 工具类 ‐‐> <dependency> <groupId>org.apache.skywalking</groupId> <artifactId>apm‐toolkit‐trace</artifactId> <vers…...

Linux驱动开发(速记版)--设备模型

第八十章 设备模型基本框架-kobject 和 kset 80.1 什么是设备模型 设备模型使Linux内核处理复杂设备更高效。 字符设备驱动适用于简单设备&#xff0c;但对于电源管理和热插拔&#xff0c;不够灵活。 设备模型允许开发人员以高级方式描述硬件及关系&#xff0c;提供API处理设备…...

动手学深度学习(李沐)PyTorch 第 6 章 卷积神经网络

李宏毅-卷积神经网络CNN 如果使用全连接层&#xff1a;第一层的weight就有3*10^7个 观察 1&#xff1a;检测模式不需要整张图像 很多重要的pattern只要看小范围即可 简化1&#xff1a;感受野 根据观察1 可以做第1个简化&#xff0c;卷积神经网络会设定一个区域&#xff0c…...

新编英语语法教程

新编英语语法教程 1. 新编英语语法教程 (第 6 版) 学生用书1.1. 目录1.2. 电子课件 References A New English Grammar Coursebook 新编英语语法教程 (第 6 版) 学生用书新编英语语法教程 (第 6 版) 教师用书 1. 新编英语语法教程 (第 6 版) 学生用书 https://erp.sflep.cn/…...

Golang 服务器虚拟化应用案例

推荐学习文档 golang应用级os框架&#xff0c;欢迎stargolang应用级os框架使用案例&#xff0c;欢迎star案例&#xff1a;基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识&#xff0c;这里有免费的golang学习笔…...

Elasticsearch基础_4.ES搜索功能

文章目录 一、搜索辅助功能1.1、指定返回的字段1.2、结果计数1.3、结果分页 二、搜索匹配功能2.1、查询所有文档2.2、term级别查询2.2.1、term查询2.2.2、terms查询2.2.3、range查询2.2.4、exists查询 2.3、布尔查询2.3.1、must&#xff0c;should&#xff0c;must_not2.3.2、f…...

Elasticsearch要点简记

Elasticsearch要点简记 1、ES概述2、基础概念&#xff08;1&#xff09;索引、文档、字段&#xff08;2&#xff09;映射&#xff08;3&#xff09;DSL 3、架构原理4、索引字段的数据类型5、ES的三种分页方式&#xff08;1&#xff09;深度分页&#xff08;fromsize&#xff09…...

【通信协议】IIC通信协议详解

IIC&#xff08;Inter-Integrated Circuit&#xff09;通信协议&#xff0c;又称为I2C&#xff08;Inter-Integrated Circuit 2&#xff09;协议&#xff0c;是一种广泛使用的串行通信协议。它由Philips Semiconductor&#xff08;现NXP Semiconductors&#xff09;开发&#x…...

2024年中国科技核心期刊目录(社会科学卷)

2024年中国科技核心期刊目录 &#xff08;社会科学卷&#xff09; 序号 期刊代码 期刊名称 1 SC02 JOURNAL OF S…...

用Python集成免费IP归属地查询API

IP查询的优势是什么&#xff1f; IP查询是一种强大的工具&#xff0c;能够快速提供关于IP地址的信息&#xff0c;如地理位置、互联网服务提供商&#xff08;ISP&#xff09;、连接类型等。这些数据在多种场景下都非常有用&#xff0c;帮助用户理解网络环境和用户行为。 首先&…...

C 数组

C 数组 数组是C语言中的一种基本数据结构&#xff0c;用于存储一系列相同类型的数据。它是连续的内存分配&#xff0c;允许通过索引快速访问元素。本文将详细介绍C数组的概念、使用方法、以及注意事项。 1. 数组的概念 数组是一个集合&#xff0c;可以存储一定数量的元素。在…...

【Unity】unity安卓打包参数(个人复习向/有不足之处欢迎指出/侵删)

1.Texture Compression 纹理压缩 设置发布后的纹理压缩格式 Use Player Settings:使用在播放器设置中设置的纹理压缩格式 ETC&#xff1a;使用ETC格式&#xff08;兼容&#xff09; ETC2&#xff1a;使用ETC2格式&#xff08;很多设备不支持&#xff09; ASTC&#xff1a;使用…...

C0016.Clion中qDebug()打印输出中文时,都是问号??????的解决办法

问题描述 在clion中使用qDebug打印输出中文内容时&#xff0c;都是&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;如下图&#xff1a; 注意&#xff1a;修改该文件的编码格式就行&#xff0c;该文件名为apr.cpp&#xff1b; 解决办法...

C++ priority_queue 优先队列构造大根堆和小根堆

priority_queue的三个参数 template <class T, class Container std::vector<T>, class Compare std::less<typename Container::value_type>> class priority_queue;1、元素类型 2、底层容器类型&#xff0c;默认vector 3、比较函数&#xff08;传入的是…...

音视频入门基础:FLV专题(9)——Script Tag简介

一、SCRIPTDATA 根据《video_file_format_spec_v10_1.pdf》第75页到76页&#xff0c;如果某个Tag的Tag header中的TagType值为18&#xff0c;表示该Tag为Script Tag&#xff08;脚本Tag&#xff0c;又称Data Tag、SCRIPTDATA tag&#xff09;。这时如果Filter的值不为1表示未加…...