添加测试数据
- 在SQLyog中执行
INSERT INTO app_bookinfo(title,bpub_date,bread,bcomment,isDelete) VALUES
('三国演义','1980-5-1',12,34,0),
('红楼梦','1986-7-24',36,40,0),
('水浒传','1995-12-24',20,80,0),
('西游记','1987-11-11',58,24,0);
INSERT INTO app_personinfo(pname,pgender,pcomment,isDelete) VALUES
('曹操',1,'字孟德',0),
('刘备',1,'字玄德',0),
('诸葛亮',1,'字孔明',0),
('孙权',1,'字仲谋',0),
('贾宝玉',1,'荣国府公子',0),
('林黛玉',0,'金陵十二钗之冠',0),
('薛宝钗',0,'薛姨妈之女',0),
('王熙凤',0,'贾琏之妻',0),
('贾母',0,'宝玉祖母',0),
('宋江',1,'呼保义',0),
('卢俊义',1,'玉麒麟',0),
('吴用',1,'智多星',0),
('公孙胜',1,'入云龙',0),
('孙悟空',1,'唐僧的大徒弟',0),
('唐僧',1,'玄奘',0),
('猪八戒',1,'悟能',0),
('沙僧',1,'沙悟净',0);
配置mysql数据库日志
通过日志文件可以查看对数据库的操作记录,mysql默认不产生日志文件,需要进行配置:
手动开启日志
进入mysql命令行:mysql -u root -p
查询日志状态:show variables like 'general_log%';
开启日志:set global general_log = 'on';
-
自动开启日志
打开mysql配置文件my.ini
,路径是C:\ProgramData\MySQL\MySQL Server 8.0
将general-log
的值修改为1
重启mysql服务
下载、安装
baretail.exe
工具在
baretail.exe
中打开日志文件,
文件位置:C:\ProgramData\MySQL\MySQL Server 8.0\Data
中在linux中使用
tail -f 日志文件
,监控日志的变化
查询函数
通过模型类.objects
属性可以调用如下函数,实现对模型类对应的数据表的查询。
函数名 | 功能 | 返回值 | 说明 |
---|---|---|---|
get | 返回表中满足条件的一条数据,并且只能是一条数据 | 模型类对象 | 参数中写查询条件。 1) 查到多条数据抛异常 MultipleObjectsReturned 2) 查询不到数据抛异常 DoesNotExist |
all | 返回表格中所有数据 | QuerySet类型 | 查询集 |
filter | 返回满足条件的数据 | QuerySet类型 | 参数写查询条件 |
exclude | 返回不满足条件的数据 | QuerySet类型 | 参数写查询条件 |
order_by | 对查询结果进行排序 | QuerySet类型 | 参数中写根据哪些字段进行排序 |
说明:
all函数以‘查询集’的形式返回所有数据表中的记录,该操作不会立限执行
只有使用了查询集中的数据时才会执行查询
实例演练
- get函数示例:查询图书id为3的图书信息
def index(request):
list = BookInfo.objects.get(id=3)
print(list.id, list.btitle, list.bpub_date, list.bread, list.bcomment)
return render(request, 'app/index.html')
- all函数示例:查询图书所有信息
def index(request):
list = BookInfo.objects.all()
for book in list:
print(book.id, book.btitle, book.bpub_date, book.bread, book.bcomment)
return render(request, 'app/index.html')
条件查询
在Django中,通过调用过滤器filter()
、exclude()
、get()
等实现SQL中的where子句
语法格式:
属性名称__比较运算符 = 值
说明:
- 属性名称和比较运算符间使用
两个下划线
- 通过"属性名_id"表示外键对应对象的id值。
条件运算符
修改views.py文件,在index视图中编写如下查询代码:
- 等值查询
exact:表示判等
例:查询编号为1的图书
list=BookInfo.objects.filter(id__exact=1)
可简写为:
list=BookInfo.objects.filter(id=1)
def index(request):
list = BookInfo.objects.filter(id__exact=1)
for book in list:
print(book.btitle, book.bpub_date)
return render(request, 'app/index.html')
- 模糊查询
contains:是否包含
说明:如果要包含%无需转义,直接写即可。
例:查询书名包含'传'的图书
list = BookInfo.objects.filter(btitle__contains='传')
startswith、endswith:以指定值开头或结尾。
例:查询书名以'梦'结尾的图书
list = BookInfo.objects.filter(btitle__endswith='梦')
以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith.
- 空查询
isnull:是否为null。
例:查询书名不为空的图书。
list = BookInfo.objects.filter(btitle__isnull=False)
- 范围查询
in:是否包含在范围内。
例:查询编号为1或3或5的图书
list = BookInfo.objects.filter(id__in=[1, 3, 5])
- 比较查询
gt、gte、lt、lte:大于、大于等于、小于、小于等于。
注意:参数中不能使用等号之外的比较符号
BookInfo.objects.filter(id > 3)
这种写法是错误的
例:查询编号大于3的图书
list = BookInfo.objects.filter(id__gt=3)
不等于的运算符,使用exclude()过滤器。
例:查询编号不等于3的图书
list = BookInfo.objects.exclude(id=3)
- 日期查询
year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。
例:查询1980年发表的图书。
list = BookInfo.objects.filter(bpub_date__year=1980)
例:查询1980年1月1日后发表的图书。
list = BookInfo.objects.filter(bpub_date__gt=date(1990, 1, 1))
- F对象
之前的查询都是属性与常量值比较,如果是两个属性比较,可以通过F对象进行
F对象被定义在django.db.models
中
语法格式:F(属性名)
例:查询阅读量大于等于评论量的图书。
from django.db.models import F
list = BookInfo.objects.filter(bread__gte=F('bcomment'))
可以在F对象上使用算数运算。
例:查询阅读量大于2倍评论量的图书
list = BookInfo.objects.filter(bread__gt=F('bcomment') * 2)
- Q对象
多个过滤器逐个调用表示逻辑与关系,相当于where子句的AND关键字。
例:查询阅读量大于20,并且编号小于3的图书。
list=BookInfo.objects.filter(bread__gt=20,id__lt=3)
或
list=BookInfo.objects.filter(bread__gt=20).filter(id__lt=3)
如果需要实现逻辑或(OR)查询,需要使用Q()对象结合 | 运算符,
Q对象被义在django.db.models中。
语法格式:Q( 属性名__运算符 = 值 )
例:查询阅读量大于20的图书,改写为Q对象如下。
from django.db.models import Q
list = BookInfo.objects.filter(Q(bread__gt=20))
Q对象可以使用&、|连接,&表示逻辑与,|表示逻辑或。
例:查询阅读量大于20,或编号小于3的图书,只能使用Q对象实现
list = BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3))
Q对象前可以使用~操作符,表示非not。
例:查询编号不等于3的图书。
list = BookInfo.objects.filter(~Q(pk=3))
聚合函数
使用aggregate()
函数调用聚合函数。
聚合函数包括:Avg
,Count
,Max
,Min
,Sum
,被定义在django.db.models
中
aggregate()
返回一个字典类型,格式为{' 属性名小写__聚合函数名小写 ' :值}
,例如:{'bread__sum':3}
例:查询图书的总阅读量。
from django.db.models import Sum
def index(request):
s = BookInfo.objects.aggregate(Sum('bread'))
print(s['bread__sum'])
return render(request, 'app/index.html')
count函数返回一个数字,一般不使用aggregate()过滤器。
例:查询图书总数。
c = BookInfo.objects.count()
查询集(QuerySet)
查询集表示从数据库中获取的对象集合,在管理器上调用某些过滤器方法会返回查询集,查询集可以含有零个、一个或多个过滤器。过滤器基于所给的参数限制查询的结果,从Sql的角度,查询集和select语句等价,过滤器像where和limit子句。
返回查询集的过滤器如下:
- all():返回所有数据。
- filter():返回满足条件的数据。
- exclude():返回满足条件之外的数据,相当于sql语句中where部分的not关键字。
- order_by():对结果进行排序。
返回单个值的过滤器如下:
- get():返回单个满足条件的对象
- 如果未找到会引发"模型类.DoesNotExist"异常。
- 如果多条被返回,会引发"模型类.MultipleObjectsReturned"异常。
- count():返回当前查询结果的总条数。
- aggregate():聚合,返回一个字典。
判断某一个查询集中是否有数据:
- exists():判断查询集中是否有数据,如果有则返回True,没有则返回False。
两大特性
- 惰性执行:创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用。
- 缓存:使用同一个查询集,第一次使用时会发生数据库的查询,然后把结果缓存下来,再次使用这个查询集时会使用缓存的数据。
示例:查询所有,编辑booktest/views.py的index视图,运行查看。
list=BookInfo.objects.all()
查询集的缓存
每个查询集都包含一个缓存来最小化对数据库的访问。
在新建的查询集中,缓存为空,首次对查询集求值时,会发生数据库查询,django会将查询的结果存在查询集的缓存中,并返回请求的结果,接下来对查询集求值将重用缓存中的结果。
- 如下是两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,产生2条SQL语句,增加了数据库的负载。
from booktest.models import BookInfo
[book.id for book in BookInfo.objects.all()]
[book.id for book in BookInfo.objects.all()]
- 经过存储后,可以重用查询集,只产生1条SQL语句,第二次使用缓存中的数据。
list=BookInfo.objects.all()
[book.id for book in list]
[book.id for book in list]
限制查询集 (LIMIT子句)
可以对查询集进行取下标或切片操作,等同于sql中的limit和offset子句,对查询集进行切片后返回一个新的查询集,不会立即执行查询
注意:不支持负数索引。
获取一个对象,直接使用[0],等同于[0:1].get(),
[0]
如果没有数据,引发IndexError
异常,
[0:1].get()
如果没有数据,引发DoesNotExist
异常。
示例:获取第1、2项,运行查看。
list=BookInfo.objects.all()[0:2]
- end -