?系列文章目录
第一章?:Django安装与配置虚拟环境
第二章:django各模块的作用以及参数说明
第三章:? Django的路由与视图
第四章:django请求
第五章:django会话
第六章:django中的cookie与session
第七章:视图类
第八章:模型类
第九章:django与mysql连接与迁移
文章目录
一、定义模型类
1.定义
2.生成迁移文件
3.同步数据库
二.测试模型类
1.增
方式一:
方式二:
2.查
基本查询
过滤查询
3.删
方法一:
方法二:
4.改
方法一:
方法二:
5.进阶
F对象:
Q对象:
聚合函数
排序
关联查询
三.补充
1.查询集
2.两大特性
惰性执行
缓存
3.管理器(Manager)
总结
前言
学习模型类之前首先要了解的是orm(Object Relational Mapping)框架,在django中内嵌了orm框架,简单来讲,orm框架帮我们把数据库中的数据表映射成一个对象,并且还能帮我们自动创建数据表,省去了我们创建表的过程。在我们想要对数据库中的数据进行操作时,只需要对相应的对象进行相关的操作即可,剩下的orm会帮我们完成。在第九章中简单介绍了下django的数据库的简单操作,在本章,进行深入的了解。
一、定义模型类
注意:
- 模型类必须继承from django.db import models下的Model
- 模型类必须卸载models.py中
1.定义
class PeopleInfo(models.Model):
name = models.CharField(verbose_name='人名', max_length=20)
book = models.ForeignKey(BookInfo, on_delete=models.PROTECT, verbose_name='外键')
jianjie = models.CharField(verbose_name='简介', max_length=200, null=True)
is_del = models.BooleanField(verbose_name='是否可用', default=False)
choices = ((0, 'nan'), (1, 'nv'))
sex = models.SmallIntegerField(verbose_name='性别', choices=choices,null=True)
class Meta:
# 指定表名
db_table = 'Peopleinfo'
# 在admin后台显示名称
verbose_name = '人物'
# 在后台显示名称不加复数
verbose_name_plural = verbose_name
def __str__(self):
# 当直接调用对象是返回该对象的name字段的数据
return self.name
主键:如果没有手动指定,django会自动创建一个主键字段id
常用字段类型与参数表
常用字段类型
数值型 | | | AutoField?? | int(11) | 自动增长主键,没有指定时由django自动创建primary_key=True(是否作为主键) | BooleanField?? | tinyint(1) | 布尔类型 | DecimalField | decimal | 定点型数据,max_digits=8(最大长度,整数加小数)decimal_places=2(精度,小数点后) | IntegerField?? | int(11) | 整型 | PositiveIntegerField | int(11) | 正整数 | SmallIntegerField | smallint | 小整数 | 字符型 | | | CharField? | varchar?? | 字符型 | URLField?? | varchar?? | 继承自字符型,实现对url的特殊处理 | UUIDField?? | char(32) | 存放固定长度的id | EmailField?? | varchar?? | 继承自字符型,实现对Email的特殊处理 | FileField?? | varchar?? | 继承自字符型,实现对file的特殊处理 | TextField? ? | longtext | 文本类型,存放大量数据 | ImageField?? | varchar?? | 继承自字符型,实现对image的特殊处理 | 日期类型 | | | dateField | data | 日期类型 | DateTimeField | datatime | 日期时间类型 | TimeField? | time | 时间类型 | 关系类型 | |
on_delete参数表示在主表数据删除时执行的操作 CASCADE 级联,主删->从删 PROTECT 保护,主删->从拦 SET_NULL 主删->从变空 SET_DEFAULT 主删->从变默认值 SET() 自定义方法 |
| ForeignKey | | 作为一对多的外键使用 | OneToOneField | | 作为一对一的外键使用(一对多的情况下限制了外键唯一) | ManyToManyField | | 作为多对多的外键使用,会创建中间表 |
常用参数
null?? | true,false | 数据库层面是否可以为空 | blank?? | true,false | 业务层面是否可以为空 | choices?? | ((数据,注释),(数据,注释),) | 在admin界面可以看到选项 | db_column?? | | 这个参数可以指定Model中的某个字段对应数据库中的哪个字段 | db_index?? | | 索引配置对于业务上需要进行作为查询条件的字段,应该配置此项 | default?? | | 默认值 | editable?? | true,false | 是否可编辑 | error_messages?? | {‘’:‘’} | 字段校验失败的提示 | help_text?? | | 提示语句 | primary_key | true,false | 设置主键 | unique?? | true,false | 唯一键 | unique_for_date?? | true,false | 一天只能出现一次 | unique_for_month | | 一月只能出现一次 | unique_for_year | | 一年只能出现一次 | verbose_name | | 别名 | validators?? | | 自定义校验逻辑 |
2.生成迁移文件
在终端中(与manage.py同目录下)使用命令python manage.py makemigrations
每一次的迁移都会生成一个迁移文件,对应数据库中的迁移表(django_migrations),迁移文件不能删除,否则会报错
3.同步数据库
?在终端中(与manage.py同目录下)使用命令python manage.py migrate
迁移文件就是为同步到数据库做准备的,django会根据迁移文件中的表,表中的字段生成对应的表
二.测试模型类
该测试中会使用到django中的shell工具,shell工具简单来讲就是交互性的执行命令的一个工具,再打开shell工具测试模型类之前,django会自动连接好数据库,配置环境。进入方式:
在终端中(与manage.py同目录下)使用命令python manage.py shell
导入模型类from books.models import BookInfo
1.增
方式一:
创建一个模型类对象,调用save方法进行保存
book = BookInfo(name = '豪豪爱吃五花肉',chuban_date = '2022-05-01')
book.save()
方式二:
调用模型类中objects的create方法直接创建并保存一条数据
BookInfo.objects.create(name = '豪豪不爱吃肉了',chuban_date = '2022-05-01')
2.查
基本查询
get:查询单一结果,参数为条件,返回一个模型类对象
all:查询集,返回一个集合
count:统计数量
>>> BookInfo.objects.get(name = '豪豪爱吃五花肉')
<BookInfo: 豪豪爱吃五花肉>
>>> BookInfo.objects.all()
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪爱吃猪肉>, <BookInfo: 豪豪爱吃五花肉>, <BookInfo: 豪豪不爱吃肉了>]>
>>> BookInfo.objects.count()
5
过滤查询
get(过滤条件):过滤出一个结果
filter(过滤条件):过滤出多个结果
exclude(过滤条件):过滤出不符合过滤条件的结果
普通过滤
过滤条件语法使用字段__关键字=值进行过滤
exact:相等关键字
contains:包含关键字
查询name包含豪豪的对象
>>> BookInfo.objects.filter(name__contains='豪豪')
<QuerySet [<BookInfo: 豪豪爱吃猪肉>, <BookInfo: 豪豪爱吃五花肉>, <BookInfo: 豪豪不爱吃肉了>]>
isnull:是否为空关键字
in:范围查询
>>> BookInfo.objects.filter(id__in=[1,2,3])
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>]>
gt :大于
查询id大于3
>>> BookInfo.objects.filter(id__gt=3)
<QuerySet [<BookInfo: 豪豪爱吃猪肉>, <BookInfo: 豪豪爱吃五花肉>, <BookInfo: 豪豪不爱吃肉了>]>
gte :大于等于
lt :小于?
lte :小于等于
日期相关的过滤
year、month、day、week_day、hour、minute、second
查询2022年出版的图书
BookInfo.objects.filter(chuban_date__year=2022)
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪爱吃猪肉>, <BookInfo: 豪豪爱吃五花肉>, <BookInfo: 豪豪不爱吃肉了>]>
查询2021年后出版的图书
>>> BookInfo.objects.filter(chuban_date__year__gt=2021)
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪爱吃猪肉>, <BookInfo: 豪豪爱吃五花肉>, <BookInfo: 豪豪不爱吃肉了>]>
3.删
方法一:
调用模型对象的delete()方法即可删除
>>> book = BookInfo.objects.get(name = '豪豪爱吃五花肉')
>>> book.delete()
(1, {'books.BookInfo': 1})
方法二:
通过过滤器查找的结果调用delete()方法删除
>>> BookInfo.objects.get(name = '豪豪爱吃猪肉').delete()
(1, {'books.BookInfo': 1})
4.改
方法一:
对查询结果调用update进行修改
>>> BookInfo.objects.filter(name = '三国演义').update(name = '红楼梦')
0
方法二:
对模型类对象单独进行修改,在调用save()进行保存
>>> book = BookInfo.objects.get(name = '西游记')
>>> book.chuban_date='1997-01-01'
>>> book.save()
5.进阶
F对象:
使用方式F('字段名')? ? 导包from django.db.models import F ?
查询阅读量等于评论量的书籍
>>> BookInfo.objects.filter(read_count=F('pinglun_count'))
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>
Q对象:
支持使用&与,|或,~非,格式 Q(过滤条件)与或非运算符Q(过滤条件)
导包? ?from django.db.models import Q
查询评论量大于0和阅读量大于0的图书
>>> BookInfo.objects.filter(Q(read_count__gt=0)&Q(pinglun_count__gt=0))
<QuerySet [<BookInfo: 西游记>]>
聚合函数
Avg(平均),Count(数量),Max(最大),Min(最小),Sum(求和),使用时候需要通过django.db.models导入,使用方式模型类.objects.aggregate(聚合函数名('字段名')),返回值类型:字典
>>> BookInfo.objects.aggregate(Sum('pinglun_count'))
{'pinglun_count__sum': 1}
排序
正序order_by(‘字段’)
倒序order_by(‘-字段’)
>>> BookInfo.objects.all().order_by('-id')
<QuerySet [<BookInfo: 豪豪不爱吃肉了>, <BookInfo: 红楼梦>, <BookInfo: 西游记>]>
>>> BookInfo.objects.all().order_by('id')
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>
关联查询
从从表向主表查询
格式(外键__主表的字段名)
查询在西游记中包含的人物
>>> PeopleInfo.objects.filter(book__name='西游记')
<QuerySet [<PeopleInfo: 孙悟空>, <PeopleInfo: 猪八戒>]>
从主表向从表查询
格式(从表的模型类名__从表字段名)
>>> BookInfo.objects.filter(peopleinfo__name='猪八戒')
<QuerySet [<BookInfo: 西游记>]>
三.补充
1.查询集<QuerySet>
调用需要返回多个对象的方法是就会返回一个查询集对象(all()返回全部,filter()返回满足条件的,exclude()返回不满足条件的,order_by()排序),比如:
>>> BookInfo.objects.all()
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>
返回的就是一个查询集
查询集可以进行再次过滤操作,也就是说多次过滤。比如:
>>> BookInfo.objects.all().filter(id__gt=3).filter(id=7)
<QuerySet [<BookInfo: 豪豪不爱吃肉了>]>
使用exists()返回查询集是否有数据
>>> BookInfo.objects.all().filter(id__gt=3).filter(id=7).exists()
True
查询集可以进行类似列表的切片操作
2.两大特性
惰性执行
创建查询集不会对数据库的数据进行查询,只有使用数据的时候才会对数据库进行查询
>>> b=BookInfo.objects.all() //不会对数据库进行查询
>>> b //使用数据时才会对数据库进行查询
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>
缓存
当使用一个变量去接受查询集的时候,第一次使用查询集会对数据库进行查询,在第二次的时候,会使用这个变量个缓存(减少数据库负载)
这样子django不会进行缓存
>>> BookInfo.objects.all()
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>
>>> BookInfo.objects.all()
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>
?这样子会把查询集缓存到q中
>>> q=BookInfo.objects.all()
>>> q
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>
>>> q
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>
3.管理器(Manager)
我们在之前进行增删改查操作时候都会使用模型类去调用objects,这个objects就是django给买一个模型类自动生成的对象。当然也可以自定义管理器对象。
总结
orm框架可以让我们完全不需要使用sql语句就可以对数据库进行各种各样的操作
|