Django为我们提供了一套与数据库交互的机制,让我们能够更便捷的对数据库进行增删改查。Django 对数据库的操作依赖于它的 ORM 系统,Django ORM 主要包括Manager、QuerySet、Model三个模块,下面将对QuerySet进行概述总结,方便在需要使用时然而又刚好忘记了的时候能够有地可查。
QuerySet 从名字就很好理解,表示对数据库进行查询的结果的集合。QuerySet是可迭代的,其包含一个或多个model instances,并且可构造、过滤、切片、遍历等。
1)延迟加载,符合筛选条件的对象被用到时才进行数据库查询;
2)缓存机制,查询数据库后的数据将缓存到内存中,当再次使用时不会再进行数据库查询,可使用all()方法对有修改的查询集进行更新
3)可下标遍历及切片,下标无负数,注意与python切片的区别;
4)对未进行求值的QuerySet进行运算,可能的返回值:QuerySet 、ValueQuerySet、ValueListQuerySet、Model,此时不进行数据库查询,反之。
5)通过当前表查询获取关联表记录时需使用select_related()或prefech_related()函数,下面有详细解释;
6)返回值为QuerySet的方法可叠加使用。
1)对查询集加步长(step)切片;
Blog.objects.all()[0:20:2] # 步长为2
2)序列化(Pickling);
3)对查询集进行遍历;
blog = Blog.objects.all()
for temple in blog:
print(temple.headline)
4)repr(),将对象转化为字符串,同python str()函数
5)len(), 求QuerySet元素的数量,推荐使用QuerySet.conunt();
6)list(), 将QuerySet转为list;
7)bool(), 判断查询集是否为空,推荐使用QuerySet.exists();
注:在QuerySet没有缓存的情况下,以上操作会导致数据库查询。
QuerySet 除提供了基础的增、删、改、查方法外,还对应SQL的关键字参数提供了一系列方法,简化了我们对数据库进行的复杂操作。
1)create() 返回当前保存的model 实例;★
Blog.objects.create(author=‘小米’, title='QuerySet详解')
2)delete() 返回None ★
Blog.objects.filter(author=‘小米’).delete()
注:需注意数据库的特性,Sqlite 不支持delete()与limit连用,对QuerySet的切片执行delete()会报错
3)update() 返回被修改的记录数 ★
Blog.objects.filter(author=‘小米’).update(title='QuerySet速查手册')
注:只可对当前表中的字段进行修改,不能修改关联表的字段值。修改关联表字段值方法:先查询得到需修改的关联表的记录,再使用update()进行修改。
4)get() 返回model 实例 ★
Blog.objects.get(id=1)
注:使用该方法时需注意返回值为model 实例,不再具有QuerySet的属性及方法。若无匹配实例,将抛出DoesNotExist异常。
5)filter() 返回QuerySet,使用查询条件对查询结果进行过滤
Blog.objects.filter(id__gt=1)
6) exclude() 返回QuerySet,对查询集过滤掉满足条件的实例。
Blog.objects.exclude(id__lte=10)
7) aggregate() 返回一个值 ★,对应聚合函数,不会使用group_by进行分组
Blog.objects.aggregate(number_of_blog=Count('title'))
8) annotate() 返回QuerySet,往每个查询集的model instances中添加一个或多个字段。执行时使用group_by进行分组后使用聚合函数返回添加值。
Blog.objects.annotate(number_of_author_blog=Count('author'))
注:
9) order_by() 返回QuerySet,对查询集进行排序
升序:
Blog.objects.filter(author=‘小米’).order_by('create_datetime')
降序:
Blog.objects.filter(author=‘小米’).order_by('-create_datetime')
10) distinct() 对元素进行去重,常与values() 及 values_list() 连用,返回与连用函数相同类型的结果集
values(*fields) 返回 列表字典类型的 ValuesQuerySet结果,格式:[{‘field_1’: value_1}, {‘field_2’: value_2},]
Blog.objects.filter(author=‘小米’).values('id','title', 'create_datetime')
# 结果
[{'id': 5}, {'title': 'QuerySet速查手册',‘create_datetime’: 2019-05-08},]
values_list(*fields) 返回 列表元组 类型的ValuesListQuerySet结果,格式:[(field_1_value, field_2_value, field_3_value)]
Blog.objects.filter(author=‘小米’).values_list('id','title', 'create_datetime')
# 结果
[(3, 'QuerySet详解', 2019-05-08),(4, 'QuerySet速查手册', 2019-05-08)]
注 当只指定一个字段时,可使用flat=True参数,使返回结果为一个列表
Blog.objects.filter(author=‘小米’).values_list('title')
# 结果
['QuerySet详解', 'QuerySet速查手册', ]
11) select_related() 返回QuerySet,在进行数据查询时不会返回关联表字段信息,在真正使用到时才去查询数据库,这样会频繁访问数据库,增加服务器压力,此时要获取关联表字段就需要使用该方法指定需要获取的关联表的记录,传入当前表的外键字段名作为参数。因此该方法只适用于一对一关系和一对多关系的正向查询,查询到的关联表记录为单条数据。数据库级使用join实现。
Blog.objects.select_related().filter(author=‘小米’)
12) prefetch_related() 返回QuerySet,与select_related()类似,但该方法适用于一对多关系的反向查询及多对多查询,查询到的关联表记录为多条数据。数据库级使用多条SQL语句联合查询,多用IN关键词进行联合。
13)extra() 返回QuerySet,用于写原生SQL语句,实现复杂的where子句,很少用。
函数原型:extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
14) get_or_create(defaults=None, **kwargs) 返回当前实例和一个bool值(objects, bool),获取或新增记录。根据所给条件查询对象,若存在则返回读取到的实例和False,若不存在则返回新创建的实例和True。★
object, bool = Blog.objects.get_or_create(author=‘小米’, title='QuerySet详解', defaults={'create_datetime': date(2019,5,9)})
注:
15)update_or_create(defaults=None, **kwargs) 返回当前实例和一个bool值(objects,bool),更新或新增记录。根据所给条件修改对象,若存在则返回修改实例和False,若不存在则返回新创建的实例和True。其他同get_or_create().★
16)bulk_create(object, batch_size=None) 批量创建, 传入的objects参数可以是一个list的object列表。★
Blog.objects.bulk_create([
Blog(author=‘小米’, title='QuerySet详解', create_datetime=date(2019,5,9)),
Blog(author=‘小咪’, title='QuerySet详解', create_datetime=date(2019,5,9)),
Blog(author=‘小洣’, title='QuerySet详解', create_datetime=date(2019,5,9)),
])
17) first() 返回当前查询集的第一个实例对象★
Blog.objects.filter(author=‘小米’).first()
18) last() 返回当前查询集的最后一个实例对象★
Blog.objects.filter(author=‘小米’).last()
19) in_bulk(id_list) 传入主键值列表,返回一个字典,该字典的key值为主键值,value值为该主键的对象
Blog.objects.in_bulk([1,2,3])
# 结果
{1:, 2:, 3:}
20) iterator() 用于查询集进行迭代,减少缓存。QuerySet具有缓存机制,查询的数据集过大时会对内存造成较大压力,而使用迭代器读取对象时,只有用到该对象时才实例化,即才从数据库进行查询,且用完后即释放内存空间。但这样又会频繁访问数据库,因此在优化性能时需要权衡。
21) latest(field_name=None) 根据传入的字段获取数据表中最新的对象,无匹配对象时会抛出DoesNotExist()异常。
22) earliest(field_name=None) 同上。
注:带★的不返回QuerySet
Q类:用于多个条件的逻辑值运算,and、or、not
F类:获取当前model中的字段用于条件运算
__gt:大于
__gte:大于等于
__lt:小于
__lte: 小于等于
Count():返回被关联model的数量
Avg():返回所给字段的平均值
distinct():返回不重复的实例数量
Max():返回查询集中所给字段的最大值
Mix():返回查询集中所给字段的最小值
Sum():返回查询集中所给字段的和
如有不对的地方,请不吝赐教,十分感谢!
本篇博文主要参考以下两篇博客,感谢作者的辛勤付出,更详细的讲解可参考他们的文章。
参考博文:
https://www.cnblogs.com/JetpropelledSnake/p/9276763.html
https://blog.csdn.net/aaronthon/article/details/81714506
☆★☆★★★☆☆☆ 鹿子