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

Django ORM详解:最全面的数据库处理指南

概要

 

深度探讨Django ORM的概念、基础使用、进阶操作以及详细解析在实际使用中如何处理数据库操作。这篇文章旨在帮助大家全面掌握Django ORM,理解其如何简化数据库操作,并透过表象理解其内部工作原理。


 

Django ORM简介

在深入讨论Django的ORM(Object-Relational Mapping,对象-关系映射)之前,让我们先理解一下什么是ORM。

ORM是一种编程技术,用于在面向对象的软件和关系数据库之间建立一种可兼容的系统。简单来说,ORM能够让你使用Python(或其他编程语言)来操作数据库,就像你在操作Python对象一样。

Django的ORM是一个非常强大的工具,它帮助你管理和查询数据库。基于Django ORM的主要优势,你可以:

  • 利用Python的对象模型进行数据库查询,无需编写复杂的SQL语句。

  • 实现数据库的平台独立性,因为Django ORM可以在多种数据库系统上运行。

下面我们用一个简单的例子来说明这个概念。假设我们有一个名为"Blog"的模型,其中有一个名为"title"的字段。使用Django ORM,我们可以轻松地查询所有标题包含"Django"的博客。

# 导入模型
from myapp.models import Blog# 使用ORM进行查询
blogs = Blog.objects.filter(title__contains='Django')# 输出查询结果
for blog in blogs:print(blog.title)

如果你在数据库中有名为"Learning Django"和"Django ORM basics"的博客,上面的代码将会输出:

Learning Django
Django ORM basics

看到这里,你可能会发现Django ORM的强大之处:它把复杂的数据库操作转化为Python对象操作,这极大地提高了我们的编程效率。


Django ORM运行机理与模型介绍

Django ORM运行机理

Django ORM将类(class)映射到数据库表(table),将类的实例(instance)映射到表的记录(record),将类的字段(field)映射到数据库的字段(column)。通过这种方式,你可以使用Python代码对数据库进行操作,而无需写任何SQL语句。

在Django ORM中,每个模型(model)对应一个数据库表,模型的字段对应表的列,模型的实例对应表的行。

Django模型介绍

在Django中,模型是对数据库表的一种高级抽象。通过定义一个模型,你可以明确地指定数据库的结构,包括数据表的名称、字段的名称和类型,以及可能的索引等。

让我们看一个简单的例子,定义一个名为“Blog”的模型:

from django.db import modelsclass Blog(models.Model):title = models.CharField(max_length=200)content = models.TextField()pub_date = models.DateTimeField(auto_now_add=True)

在这个例子中,我们定义了一个名为Blog的模型,它有三个字段:titlecontentpub_date。每个字段都对应一种数据库的列类型:CharField对应字符类型,TextField对应文本类型,DateTimeField对应日期时间类型。


Django模型Model深入理解

定义模型

在Django中,模型是数据访问层的核心组成部分,它为你的数据定义了最重要的行为。模型是一个Python类,子类于django.db.models.Model。每个模型都对应一个数据库表。

from django.db import modelsclass Blog(models.Model):title = models.CharField(max_length=200)content = models.TextField()pub_date = models.DateTimeField(auto_now_add=True)

上面的例子中,我们定义了一个名为Blog的模型,它有三个字段:titlecontentpub_date

模型字段类型

Django提供了许多内置的字段类型,可以满足大部分的数据库设计需求。例如:

  • CharField:字符字段,用于存储较短的字符串,如标题。

  • TextField:文本字段,用于存储大量文本,如博客内容。

  • DateTimeField:日期时间字段,用于存储日期和时间。

每种字段类型都有其特定的参数,例如CharField需要一个max_length参数,指定该字段的最大长度。

模型关联关系

Django的模型还可以定义复杂的关联关系,包括一对一(OneToOne)、一对多(ForeignKey)和多对多(ManyToMany)关系。

例如,我们可以定义一个Author模型,并将其与Blog模型关联:

class Author(models.Model):name = models.CharField(max_length=100)class Blog(models.Model):title = models.CharField(max_length=200)content = models.TextField()pub_date = models.DateTimeField(auto_now_add=True)author = models.ForeignKey(Author, on_delete=models.CASCADE)

这里我们为Blog模型添加了一个author字段,它是一个外键字段(ForeignKey),指向Author模型。这意味着每篇博客都有一个作者,而每个作者可以写多篇博客。

当我们删除一个作者时,on_delete=models.CASCADE参数将确保所有关联的博客也会被删除。


Django ORM增删改查CRUD操作

在了解了Django模型后,我们来看看如何使用Django ORM进行常见的数据库操作:创建(Create)、读取(Retrieve)、更新(Update)和删除(Delete),通常被称为CRUD操作。

创建记录

在Django ORM中,我们可以通过创建模型的实例来创建新的记录。以下是一个创建新的Blog记录的示例:

from myapp.models import Blog# 创建新的Blog实例
blog = Blog(title='My first blog', content='This is my first blog post.')
blog.save()  # don't forget to call save method

save()方法会将新的Blog实例保存到数据库中。

读取记录

Django ORM提供了多种方法来读取数据库中的记录。我们可以使用all()方法获取所有记录,也可以使用filter()方法获取满足特定条件的记录。

from myapp.models import Blog# 获取所有Blog记录
blogs = Blog.objects.all()# 输出所有Blog的标题
for blog in blogs:print(blog.title)

如果有一个名为"My first blog"的博客,上面的代码将会输出:

My first blog

更新记录

更新数据库中的记录也很简单。我们可以获取一个记录的实例,修改它的属性,然后调用save()方法:

from myapp.models import Blog# 获取第一个Blog记录
blog = Blog.objects.first()# 更新标题
blog.title = 'My updated blog'
blog.save()

这段代码将更新数据库中第一个博客的标题。

删除记录

要删除数据库中的记录,我们可以获取一个记录的实例,然后调用delete()方法:

from myapp.models import Blog# 获取第一个Blog记录
blog = Blog.objects.first()# 删除记录
blog.delete()

这段代码将删除数据库中的第一个博客。


Django ORM数据库进阶操作

在掌握了Django ORM的基础操作后,接下来我们来看看一些更高级的数据库操作,包括复杂查询、查询优化等。

复杂查询

在Django ORM中,我们可以使用filter()exclude()order_by()等方法进行复杂查询。

例如,我们可以找到所有标题包含"django"的博客,并按照发布日期降序排序:

from myapp.models import Blog# 获取所有标题包含'django'的Blog记录,并按照发布日期降序排序
blogs = Blog.objects.filter(title__contains='django').order_by('-pub_date')# 输出这些Blog的标题
for blog in blogs:print(blog.title)

如果存在标题包含'django'的博客,上述代码将会按照发布日期的降序打印它们的标题。

查询优化

对于大型数据库,优化查询是非常重要的。Django ORM提供了几种工具来帮助你优化查询,包括select_related()prefetch_related()

select_related()可以一次性获取与查询对象有ForeignKey关联的对象,这可以减少数据库查询次数:

from myapp.models import Blog# 获取所有Blog记录,并一次性获取每个Blog的author信息
blogs = Blog.objects.select_related('author').all()# 输出Blog的标题和作者名
for blog in blogs:print(blog.title, blog.author.name)

如果有作者名为'John'且标题为"My first blog"的博客,上述代码将会输出:

My first blog John

prefetch_related()对于ManyToMany关联和一对多关联也非常有用,它可以一次性获取所有相关对象,减少数据库查询次数。


利用数据库约束保证数据一致性

Django ORM提供了多种数据库约束,如uniquecheck等,可以帮助我们确保数据库的数据一致性。

# 例子:使用unique约束确保每个作者的email是唯一的
class Author(models.Model):name = models.CharField(max_length=100)email = models.EmailField(unique=True)

使用批量操作提升性能

Django ORM提供了bulk_createbulk_update等方法,可以让我们以更高效的方式进行批量创建和更新。

# 例子:使用bulk_create方法批量创建对象
authors = [Author(name=f'Author {i}') for i in range(1000)]
Author.objects.bulk_create(authors)  # 这个操作只需要一次数据库查询

使用原生SQL

尽管Django ORM提供了许多强大的查询工具,但有时候你可能需要直接执行SQL语句。Django ORM允许你执行原生SQL,你可以使用raw()方法或者cursor()方法来执行原生SQL:

from django.db import connection# 使用cursor()执行原生SQL
with connection.cursor() as cursor:cursor.execute("SELECT title FROM myapp_blog")row = cursor.fetchone()print(row)

这段代码将直接执行SQL查询,并打印出第一个博客的标题。虽然Django ORM提供了.raw()方法允许我们直接执行SQL查询,但是这个方法应该尽量避免使用,因为它可能会引发SQL注入等安全问题,同时也失去了Django ORM的许多优点。


Django数据库迁移

Django的数据库迁移系统能够自动地将你对模型的更改(增加字段、删除模型等)转换为SQL命令,并在数据库中执行这些命令。这是一种对数据库进行版本控制的方式,让你能够更改你的模型并保持数据库的更新。

创建迁移

当你更改了你的模型(例如,添加一个字段、改变一个字段的类型等),你需要创建一个迁移来将这些更改应用到数据库。你可以使用makemigrations命令来创建迁移:

python manage.py makemigrations your_app_name

上述命令将会检查你的模型与数据库的当前状态,然后创建一个新的迁移,该迁移包含了将数据库更新至新状态所需的所有操作。

应用迁移

创建了迁移之后,你需要使用migrate命令来应用这些更改到数据库:

python manage.py migrate

该命令将执行所有未应用的迁移,将你的数据库更新至最新状态。

查看迁移状态

你可以使用showmigrations命令查看所有迁移的状态(已应用的和未应用的):

python manage.py showmigrations

执行上述命令将会列出所有的迁移以及它们的状态,这可以帮助你了解数据库的当前状态。

回滚迁移

有时,你可能需要撤销某个迁移。你可以使用migrate命令和迁移名(或迁移名之前的迁移名)来回滚迁移:

python manage.py migrate your_app_name 0001

该命令将会撤销名为0002的迁移(以及在其之后的所有迁移),并将数据库回滚至0001的状态。


Django ORM的不足点

尽管Django ORM是一个强大且方便的工具,但它并不是无懈可击的。了解这些局限性可以帮助我们更加理智地决定何时以及如何使用它。

性能开销

Django ORM需要额外的处理来将数据库的行转换为Python对象。这意味着使用Django ORM通常会比直接使用SQL语句慢一些。然而,这种性能开销通常是可以接受的,除非你正在处理极大量的数据。

不支持某些复杂的SQL查询

虽然Django ORM支持许多SQL功能,但有一些复杂的SQL查询可能无法通过Django ORM的查询API来实现。例如,对于某些数据库的特定特性或高级SQL功能,可能需要写原生的SQL语句。

需要额外的学习和理解

虽然Django ORM可以帮助我们避免直接编写SQL,但是要有效地使用它,仍然需要理解数据库的基本概念。而且,Django ORM自身的API和特性也需要一些学习和理解。

对数据库的隐藏可能导致误解

Django ORM隐藏了数据库的许多细节,这使得编程变得更简单,但也可能导致开发者对正在执行的数据库操作有误解。例如,一个看似简单的操作可能实际上引发了多次数据库查询。

# 例子:看似简单的操作实际上引发了多次数据库查询
for book in Book.objects.all():print(book.author.name)  # 这个操作对每本书都会引发一个数据库查询

在这个例子中,打印每本书的作者名字的操作实际上对每本书都会引发一个数据库查询,如果有大量的书籍,那么这个操作将会非常慢。这是因为Django ORM默认是懒加载的,也就是说,它只在需要的时候才会去数据库查询数据。


Django ORM总结与展望

经过这篇文章的学习,我们深入了解了Django ORM的工作原理,实现了一些基础和进阶的数据库操作,同时也了解了它的一些最佳实践和局限性。

Django ORM作为Python Web开发中的一个重要部分,它以其简洁和强大的功能赢得了许多开发者的喜爱。尽管它有一些局限性,比如某些复杂查询的支持不是很好,以及它对数据库操作的隐藏可能会导致性能问题,但是总体来说,Django ORM是一个非常有效的工具,可以帮助我们更快更好地进行Web开发。

在未来,我们可以期待Django ORM将会持续改进,提供更多的功能和更好的性能。同时,我们也可以通过深入学习和实践,更好地利用Django ORM,提高我们的开发效率。

 

今天的分享就到这里,如果文章内容对你有所帮助,欢迎点赞收藏转发,感谢🙏

相关文章:

Django ORM详解:最全面的数据库处理指南

概要 深度探讨Django ORM的概念、基础使用、进阶操作以及详细解析在实际使用中如何处理数据库操作。这篇文章旨在帮助大家全面掌握Django ORM,理解其如何简化数据库操作,并透过表象理解其内部工作原理。 Django ORM简介 在深入讨论Django的ORM&#xff…...

Istio 安全 授权管理AuthorizationPolicy

这个和cka考试里面的网络策略是类似的。它是可以实现更加细颗粒度限制的。 本质其实就是设置谁可以访问,谁不可以访问。默认命名空间是没有AuthorizationPolicy---允许所有的客户端访问。 这里是没有指定应用到谁上面去,有没有指定使用哪些客户端&#…...

04 Ubuntu中的中文输入法的安装

在Ubuntu22.04这种版本相对较高的系统中安装中文输入法,一般推荐使用fctix5,相比于其他的输入法,这款输入法的推荐词要好得多,而且不会像ibus一样莫名其妙地失灵。 首先感谢文章《滑动验证页面》,我是根据这篇文章的教…...

faac内存开销较大,为方便嵌入式设备使用进行优化(valgrind使用)

faac内存开销较大,为方便嵌入式设备使用进行优化,在github上提了issues但是没人理我,所以就搞一份代码自己玩吧。 基于faac_1_30版本,原工程https://github.com/knik0/faac faac内存优化: faac内存开销较大,为方便嵌入…...

分数线划定(c++题解)

题目描述 世博会志愿者的选拔工作正在 A 市如火如荼的进行。为了选拔最合适的人才,A 市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试。面试分数线根据计划录取人数的 150% 划定,即如果计划录取 m 名志愿者&#xf…...

React 在 html 中 CDN 引入(包含 antd、axios ....)

一、简介 cdn 获取推荐 https://unpkg.com&#xff0c;unpkg 是一个快速的全球内容交付网络&#xff0c;适用于 npm 上所有内容。 【必备】react 相关 cdn。附&#xff1a;github 官方文档获取、现阶段官方文档 CDN 网址。 <script crossorigin src"https://unpkg.com…...

数据结构----异或

数据结构----异或 一.何处用到了异或 1. 运算符 //判断是否相同 用到了异或&#xff0c;看异或结果如果是0就是相同&#xff0c;不是0就是不同//注意&#xff1a; 不能给小数用&#xff0c;小数没有相等的概念&#xff0c;所以小数判断是否相同都是进行相减判断2.找一堆数中…...

PHP Smarty模板的语法规则是怎样的?

首先&#xff0c;你要知道Smarty模板是以模板格式来编写的。模板格式类似于HTML&#xff0c;但它的语法更加简洁明了。 以下是PHP Smarty模板的语法规则和代码例子&#xff1a; 变量&#xff1a;在Smarty模板中&#xff0c;你可以使用变量来显示动态内容。变量通常以“{$”符…...

Socks IP轮换:为什么是数据挖掘和Web爬取的最佳选择?

在数据挖掘和Web爬取的过程中&#xff0c;IP轮换是一个非常重要的概念。数据挖掘和Web爬取需要从多个网站或来源获取数据&#xff0c;而这些网站通常会对来自同一IP地址的请求进行限制或封锁。为了避免这些问题&#xff0c;数据挖掘和Web爬取过程中需要使用Socks IP轮换技术。在…...

优化|当机器学习上运筹学:PyEPO与端对端预测后优化

分享者&#xff1a;唐博 编者按&#xff1a;​ 这篇文章我想要写已经很久了&#xff0c;毕竟“端对端预测后优化”&#xff08;End-to-End Predict-then-Optimize&#xff09;正是我读博期间的主要研究方向&#xff0c;但我又一直迟迟没能下笔。想说自己杂事缠身&#xff08;实…...

Cocos Creator的 Cannot read property ‘applyForce‘ of undefined报错

序&#xff1a; 1、博主是看了这个教程操作的时候出的bug>游戏开发 | 17节课学会如何用Cocos Creator制作3D跑酷游戏 | P9 代码控制对象移动_哔哩哔哩_bilibili 2、其实问题不是出在代码上&#xff0c;但是发现物体就是不平移 3、node全栈的资料》node全栈框架 正文…...

纯css实现九宫格图片

本篇文章所分享的内容主要涉及到结构伪类选择器&#xff0c;不熟悉的小伙伴可以了解一下&#xff0c;在常用的css选择器中我也有分享相关内容。 话不多说&#xff0c;接下来我们直接上代码&#xff1a; <!DOCTYPE html> <html lang"en"><head>&l…...

【MySQL】数据库的增删查改+备份与恢复

文章目录 一、创建数据库create二、数据库所使用的编码2.1 查询字符集和校验集2.2 指定编码创建数据库2.3 不同的校验集对比 三、删除数据库drop四、查看数据库show五、修改数据库alter六、数据库的备份与恢复6.1 备份 mysqldump6.2 恢复source6.3 仅备份几张表或备份多个数据库…...

Docker 部署 redis 举例

1、搜索镜像&#xff0c;也可以访问 https://hub.docker.com/ 搜索镜像&#xff0c;查看所有版本。 $ docker search redis2、拉取镜像 $ docker pull redis:5.03、启动镜像&#xff0c;并配置相关映射与绑定&#xff08;附&#xff1a;Docker 常用命令与指令参数&#xff09…...

通过HandlerMethodArgumentResolver实现统一添加接口入参参数

背景&#xff1a;项目中有些接口的入参需要用户id信息&#xff0c;最简单的做法在每个Controller方法调用的时候获取登录信息然后给入参设置用户id&#xff0c;但是这样就会有很多重复性的工作。另一个可行的也更好的方案可以使用HandlerMethodArgumentResolver来实现。 部分示…...

JAVA-spring boot 2.4.X报错Unable to find GatewayFilterFactory with name Hystrix

网关升级spring boot项目后&#xff0c;启动网关报错&#xff0c;具体报错信息如下: 2021-12-06 09:06:25.335 ERROR 45102 --- [oundedElastic-3] reactor.core.publisher.Operators : Operator called default onErrorDropped reactor.core.Exceptions$ErrorCallback…...

运输层---UDP协议

目录 一. 无连接运输&#xff1a;UDP1.1 定义1.2 特点1.3 应用 二. UDP报文段结构三. UDP检验和3.1 定义3.2 检验和计算实例3.2 UDP检验和的局限 一. 无连接运输&#xff1a;UDP 1.1 定义 UDP&#xff08;User Datagram Protocol&#xff09;用户数据报协议&#xff1a;由 [RF…...

【LeetCode】剑指 Offer Ⅱ 第3章:字符串(7道题) -- Java Version

题库链接&#xff1a;https://leetcode.cn/problem-list/e8X3pBZi/ 题目解决方案剑指 Offer II 014. 字符串中的变位词双指针 数组模拟哈希表 ⭐剑指 Offer II 015. 找到字符串中所有字母异位词双指针 数组模拟哈希表 ⭐剑指 Offer II 016. 不含重复字符的最长子字符串双指针…...

【python】绘图代码模板

【python】绘图代码模板 pandas.DataFrame.plot( )画图函数Seaborn绘图 -数据可视化必备主题样式导入数据集可视化统计关系散点图抖动图箱线图小提琴图Pointplot群图 可视化数据集的分布绘制单变量分布柱状图直方图 绘制双变量分布Hex图KDE 图可视化数据集中的成对关系 好看的图…...

RTT学习笔记12-KConfig 语法学习

KConfig 语法学习 RTT 官方教程 https://www.rt-thread.org/document/site/#/development-tools/build-config-system/Kconfig 我自己写的IIC配置 menuconfig BSP_USING_I2C # I2C 菜单bool "Enable I2C BUS" # 提示I2C 菜单default n # 默认不使能I2C 菜单…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...