Django基础(6):ORM系统:单表操作
1|0一、ORM 简介
1|11.1. web开发的分工模式
-
一般中大型公司(或者数据量巨大、读取数据的需求频繁并且追求极致效率的公司)会有专门的DBA管理数据库,编写sql语句,对于应用层开发来说,不用写sql语句,直接调用他写的接口就行。所以在这种公司一般来说,开发人员应该'供'着DBA,因为你想写入或者取出的数据需要依赖于DBA去执行,或者是你写的比较复杂的sql语句需要让DBA帮你看一下,效率行不行、是不是需要优化等等,这就需要看你们的交情或者其心情了。哈哈(开个玩笑)。
-
应用程序开发+sql语句编写。
这种情况多存在于小公司,没有专门设置DBA岗位,要求开发人员什么都会一些,linux、数据库、前端等等,这样成本降低并且减少由于部门之间的沟通带来的损失,提高工作流程效率。
-
应用程序开发+ORM。
1|21.2 ORM 概念
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。
简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
ORM在业务逻辑层和数据库层之间充当了桥梁的作用。
1|31.3 ORM由来
让我们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。
几乎所有的软件开发过程中都会涉及到对象和关系数据库。在用户层面和业务逻辑层面,我们是面向对象的。当对象的信息发生变化的时候,我们就需要把对象的信息保存在关系数据库中。
按照之前的方式来进行开发就会出现程序员会在自己的业务逻辑代码中夹杂很多SQL语句用来增加、读取、修改、删除相关数据,而这些代码通常都是重复的。
ORM优势
- 提高开发效率。
- 不同数据库可以平滑切换。
- 让软件开发人员专注于业务逻辑的处理,提高了开发效率。
- ORM 代码转换为 SQL 语句时,需要花费一定的时间,执行效率会有所降低。
- 长期写 ORM 代码,会降低编写 SQL 语句的能力。
ORM 解析过程
- ORM 会将 Python 代码转成为 SQL 语句。
- SQL 语句通过 pymysql 传送到数据库服务端。
- 在数据库中执行 SQL 语句并将结果返回。
2|0二、数据库配置
2|12.1 Django 如何使用 mysql 数据库
创建 MySQL 数据库( ORM 无法操作到数据库级别,只能操作到数据表)语法:
例如常见 runoob 数据库,编码指定为 utf8:
我们在项目的 settings.py 文件中找到 DATABASES 配置项,将其信息修改为:
上面包含数据库名称和用户的信息,它们与 MySQL 中对应数据库和用户的设置相同。Django 根据这一设置,与 MySQL 中相应的数据库和用户连接起来。
上面是给项目中的所有的应用都配置成MySQL数据库,当然我们也可以给单个应用配置数据库:
接下来,告诉 Django 使用 pymysql 模块连接 mysql 数据库:
2|22.2 同一个app使用不同的库
settings
views
3|0三、定义模型
3|13.1 创建 APP
Django 规定,如果要使用模型,必须要创建一个 app。我们使用以下命令创建一个 TestModel 的 app:
结构目录如下
我们修改 TestModel/models.py 文件,代码如下:
以上的类名代表了数据库表名,且继承了models.Model,类里面的字段代表数据表中的字段(name),数据类型则由CharField(相当于varchar)、DateField(相当于datetime), max_length 参数限定长度。
接下来在 settings.py 中找到INSTALLED_APPS这一项,如下:
在对应数据库中生成表结构
对应的app下面,migrations出现一个0001_initial.py的文件,这个文件是你执行了上述指令之后产生的脚本文件,这个文件就是一个记录。
接下来我们继续输入指令:
看到几行 "Creating table…" 的字样,你的数据表就创建好了。
这个指令其实就是执行第一个指令生成的记录也就是那个脚本文件,然后就会在你对应的数据库中生成一个真正的表,生成的表名字前面会自带应用的名字,例如:你的userinfo表在数据表里面叫做:app01_userinfo。
注意:尽管我们没有在 models 给表设置主键,但是 Django 会自动添加一个 id 作为主键。
创建的时候除了自己创建的表,还会创建一些django自带的表。
一些说明:
- 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时。
- id 字段是自动添加的,如果你想要指定自定义主键,只需在其中一个字段中指定 primary_key=True 即可。如果Django发现你已经明确地设置了Field.primary_key,它将不会添加自动ID列。
- 本示例中的CREATE TABLE SQL使用PostgreSQL语法进行格式化,但值得注意的是,Django会根据配置文件中指定的数据库后端类型来生成相应的SQL语句。
- Django支持MySQL5.5及更高版本。
3|23.2 自定义表名及字段名称(db_column和verbose_name)
-
指定字段名: 在定义字段的时候,增加参数db_column=’real_field’;
-
例如在某个models.py文件中,有一个类叫Info:
其中db_column指定了对应的字段名,db_table指定了对应的表明;
如果不这样指定,字段名默认为app_name, 而表明默认为app名+类名: [app_name]_info.
verbose_name指定在admin管理界面中显示中文;verbose_name表示单数形式的显示,verbose_name_plural表示复数形式的显示;中文的单数和复数一般不作区别。
3|33.3 choice
由二项元组构成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,而且这个选择框的选项就是choices 中的选项。
这是一个关于 choices 列表的例子:
每个元组中的第一个元素,是存储在数据库中的值;第二个元素是在管理界面或 ModelChoiceField 中用作显示的内容。 在一个给定的 model 类的实例中,想得到某个 choices 字段的显示值,就调用 get_FOO_display 方法(这里的 FOO 就是 choices 字段的名称 )。例如:
源码
模板里获取 choice 显示的值:
view 里获取 choice 显示的值:
4|0四、ORM 常用字段和参数
4|14.1 常用字段
AutoField
int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。
IntegerField
一个整数类型,范围在 -2147483648 to 2147483647。
CharField
字符类型,必须提供max_length参数, max_length表示字符长度。
DateField
日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例。
DateTimeField
日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。
4|24.2 字段合集(争取记忆)
4|34.3 自定义字段(了解为主)
自定义char类型字段:
创建的表结构:
附ORM字段与数据库实际字段的对应关系
4|44.4 参数字段
关于auto_now,你需要知道的事情:
5|0五、单表操作
5|15.1 增:添加表记录
首先我们先要做一个简单的流程,方便我们测试:
然后我们通过在index函数中构建一些逻辑,展示我们对单表的增删改查。在研究增删改查之前我们一定要明确ORM的对应关系:
在python中orm的对应关系有三种:
类 ----------> 表
类的对象 ----------> 行(记录)
类的属性 ----------> 表的字段(重点)
我们要想操作一行的数据,就应该将相应的类引入,然后通过实例化对象增加数据。接下来,我们重新创建一个数据库为orm01,创建一个student表结构,从这个表中去研究单表的操作。
这里需要注意:
1. 更改settings里面的数据库配置:orm01.
2. 在models文件中创建student类:
3. 生成记录并且创建表结构
接下来我们就开始研究如何增加表记录。
前提:要在views中导入对应app的models。from appname import models
方式1:模型类实例化对象
从index函数中操作:
查看数据表:我们添加成功了。
方式2:通过 ORM 提供的 objects 提供的方法 create 来实现(推荐)
我们通过方式1给student表中添加了一条表记录,但是上面那种方法不灵活,接下来我们介绍一种更加灵活的方法。
objects比较特殊,我们称它为类对应的控制器,这个控制器对象可以调用数据表相应的增删改查等方法,非常灵活。
这样以来我们就添加成功了:
而且我们通过查询create方法的源码可以得知:
他可以创建一个新的对象保存到相应的数据表中,并且返回这个新创建的对象。那么接下来我们查看一下他的返回值并输入一下:
这样它既向我们的数据表中添加了值,又将创建的对象返回了:
那么,以后我们就将这种(models类的对象)称之为model对象。(很重要一定要记住)
方式3:批量创建
我们以后工作中肯定会让你批量插入很多数据,怎么解决?有同学肯定会说循环create,但是每次create都需要操作数据库,这是一个IO操作,如果这样的话数据量越大,你的效率越低。所以针对这种情况我们可以通过批量创建。
假如我们依次插入20条数据:
方式4:更新或增加
orm还有一种方法是对一条表记录进行更新或者增加的操作:有则更新无则增加,类似于字典的这个操作dic['name'] = 'barry'。
5|25.2 查询
本来我们应该研究删除表记录,但是我们这里先要研究几个简单的查询,因为这些查询返回两种特殊的对象,对于不同的对象他们的删、改的的方法不同。
1.all()全部取出
通过all从orm取出来的是一个QuerySet类型,这里面有很多个Student类的对象也就是model对象,这个QuerySet类似于列表,但是不同与列表,后面我们会详细对比讨论,在这里我们知道可以循环遍历取值即可。
model对象与queryset集合是我们经常用的两个对象,一定要分清楚。
上面我们for循环遍历时,每次都需要.name获取name属性,比较麻烦,我们可以不可以直接打印对象获取对应的姓名呢?这就要想到特殊的双下方法__str__.我们可以在Student类中定一个__str__方法,这样以后我们就可以用于调试了。
2.filter(条件) 条件查询
通过条件查询获取结果,返回的也是QuerySet类型,如果查询不到内容不会报错,返回一个空的QuerySet集合。
3.get(条件) 条件查询
这个get比较特殊,它返回的是model对象,通过get条件查询,查询的结果有且只有1个。
如果超过一个则报错为:get() returned more than one Student -- it returned 2(有几个显示几个)!
如果没有则报错为:Student matching query does not exist.
所以一般如果我们使用get条件查询,前提一定要确定你的条件锁定的就是一条行记录。
5|35.3. 删:删除行记录
1. 删除单个对象,调用model对象删除
这样就是删除单条记录
2.批量删除,调用QuerySet集合删除
这样就是批量删除记录,满足条件的记录都会被删除。
(等学到外键的时候再说) 在 Django 删除对象时,会模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。例如:
要注意的是: delete() 方法是 QuerySet 上的方法,但并不适用于 Manager 本身。这是一种保护机制,是为了避免意外地调用 Entry.objects.delete() 方法导致 所有的 记录被误删除。如果你确认要删除所有的对象,那么你必须显式地调用:
如果不想级联删除,可以设置为:
5|45.4.改:更新行记录
批量修改使用 QuerySet 的 update(属性=值) 方法
更新记录的方法只有一个就是update,此方法只能用于QuerySet集合,model对象是不可以使用的。也就是说update可以进行批量更新的操作,并且他会返回一个更新的行记录数量的返回值。
5|55.5.查:查看(获取)行记录
查询是数据库增删改查的重中之重,方法非常多,大家一定要好好练习。前三个我们都练习过了可以在练习一遍。
1.all()全部取出
通过object控制器调用,返回QuerySet类型。
通过all从orm取出来的是一个QuerySet类型,这里面有很多个Student类的对象也就是model对象,这个QuerySet类似于列表,但是不同与列表,后面我们会详细对比讨论,在这里我们知道可以循环遍历取值即可。
2.filter(条件) 条件查询
通过object控制器调用,返回QuerySet类型。
通过条件查询获取结果,返回的也是QuerySet类型,如果查询不到内容不会报错,返回一个空的QuerySet集合。
还可以进行多条件查询:
还可以通过打散字典的形式进行筛选
注意:
1. 一定要记住每个方法是通过哪种类型调用,以及返回哪种类型。这样我们方便可以通过链式点的操作进行复杂查询。
2. filter一种是关键字形式,一个是字符串形式,很重要,这两个就可以解决不同的需求了。
3.get(条件) 条件查询
通过object控制器调用,返回model对象
这个get比较特殊,它返回的是model对象,通过get条件查询,查询的结果有且只有1个。
如果超过一个则报错为:get() returned more than one Student -- it returned 2(有几个显示几个)!
如果没有则报错为:Student matching query does not exist.
4.exclude排除
通过object对象或者QuerySet集合调用,返回QuserySet集合。
下面我们演示了上面说到的链式点操作,可以一直进行点的操作,因为此方法可以QuerySet集合调用,并且返回的还是QuerySet集合。
5.order_by排序
通过object对象或者QuerySet集合调用,返回QuserySet集合。
通过年龄升序排列,相同年龄的按照id降序排列:
6.reverse反转
通过order_by返回的QuerySet集合调用,返回一个QuerySet集合。
7.count计数
通过QuerySet集合调用,返回一个元素个数。
8.first返回第一个model对象
通过QuerySet集合调用,返回第一个model对象
9.last返回最后一个model对象
通过QuerySet集合调用,返回最后一个model对象
10.exists判断是否存在
通过QuerySet集合调用,返回bool值
这里我们要说一句,他的效率是高的,尤其是作为if判断的条件。
我们也可以通过配置settings,每次执行orm语句时都将相应的sql语句展示出来,这样可以查看一下exists().
settings配置:
再次执行一次:
11.values_list
通过QuerySet集合调用,返回一个QuerySet集合
但是这个QuerySet集合比较特殊,这个里面的元素不是model对象,而是元组的形式。
还可以指定想获取的字段:
12.values
通过QuerySet集合调用,返回一个QuerySet集合
但是这个QuerySet集合比较特殊,这个里面的元素不是model对象,而是字典的形式。
13.distinct去重
通过QuerySet集合调用,返回一个QuerySet集合
这里要注意一点:无论是all还是filter 你对整个对象去重是没有意义的,只要有一个字段不同,都不是重复的。
所以这个去重一般都用于values或者values_list。
14.基于双下划线的模糊查询
我们在使用filter方法时,一直在使用 = 条件,但是没有使用过> < >=等条件,这是因为ORM不支持这种写法,不用着急,我们可以根据另一种写法去实现。
15.日期
日期这个字段查询起来比较特殊,我们单独拿出来讲解,现在我们要重新创建一个表。
别忘了生成记录以及创建到数据库中。
查看一下表结构:
注意date字段,这个字段要求的是date类型,我们如果存放的是datetime类型也是可以的,只不过只是显示年月日。
接下来我们给表中插入一些数据:
对应的数据库的数据为:
查询2000年出生的人,这样写就会报错了:
查询2000年出生的人:
查询2000年4月出生的人:
查询2000年大于4月小于12月出生的人:
6|0从已经建好的表中导出orm配置
也可以重定向一下到某个文件
__EOF__

本文链接:https://www.cnblogs.com/dongye95/p/13582484.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!