Django QuerySet API 文档阅读(3):QuerySet定义(一)
原文地址:QuerySet API reference | Django documentation | Django
QuerySet有两个属性,ordered和db;
ordered:返回语句是否排序。True or False。
db:返回连接的数据库,默认 "default" 数据库。
可以使用链式调用组成查询语句,返回new QuerySet对象的方法有:
- filter()
- exclude()
- annotate()
- alias()
- order_by()
- reverse()
- distinct()
- values()
- values_list()
- dates()
- datetimes()
- none()
- all()
- union()
- intersection()
- difference()
- select_related()
- prefetch_related()
- extra()
- defer()
- only()
- using()
- select_for_update()
- raw()
filter
filter(**kwargs)
返回满足条件的新的查询集,效果 = WHERE,不同的条件间默认逻辑符号为AND,即
Student.object.filter(hobby="乒乓球", gender="women")
等价于 SELECT * FROM STUDENT WHERE hobby="乒乓球" AND gender="women"
exclude
返回不满足所有条件的行,和filter是相反的结果。
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')
排除那些 headline为Hello且发行日期大于2005年1月3日的行。
等价于SQL
SELECT ... WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')
annotate
为查询集的每一项生成聚合,常用于分组统计,返回的查询集对象中添加一项聚合值。
例子1:按学生分组,统计每个学生的爱好数量
student = Student.objects.annotate(Count('hobbies'))
其中 student 增加了一项 hobbies__count 属性,支持自定义聚合字段名
student = Student.objects.annotate(hobby_count_by_student=Count('hobbies'))
其中 student 增加了一项 hobby_count_by_student 属性。
例子2:和filter方法联用
有时我们需要先对数据集先筛选再分组,有时我们还需要先分组再对查询集进行筛选。根据需求不同,我们可以合理地联用annotate方法和filter方法。注意: annotate和filter方法联用时使用顺序很重要。
# 先按爱好分组,再统计每组学生数量, 然后筛选出学生数量大于1的爱好。
Hobby.objects.annotate(student_num=Count('student')).filter(student_num__gt=1)# 先按爱好分组,筛选出以'd'开头的爱好,再统计每组学生数量。
Hobby.objects.filter(name__startswith="d").annotate(student_num=Count('student‘))
例子3:和order_by方法联用
可以使用order_by方法对annotate方法返回的数据集进行排序。
# 先按爱好分组,再统计每组学生数量, 然后按每组学生数量大小对爱好排序。
Hobby.objects.annotate(student_num=Count('student')) \.order_by('student_num')# 统计最受学生欢迎的5个爱好。
Hobby.objects.annotate(student_num=Count('student')) \.order_by('-student_num')[:5]
例子4:和values联用
在前例中按学生对象进行分组,我们同样可以按学生姓名name来进行分组。唯一区别是本例中,如果两个学生具有相同名字,那么他们的爱好数量将叠加。
# 按学生名字分组,统计每个学生的爱好数量。Student.objects.values('name').annotate(Count('hobbies'))# 你还可以使用values方法从annotate返回的数据集里提取你所需要的字段,如下所示:# 按学生名字分组,统计每个学生的爱好数量。Student.objects.annotate(hobby_count=Count('hobbies'))\ .values('name', 'hobby_count')
最近我又发现 annotate 一个好使的方面,就是给人为添加字段,比如说由于某种历史原因,查询语句为auth_time__range(日期1,日期2),原来的表字段为 auth_time 后来改名为 time 了,为了兼容,可以添加人为给查询结果添加一个auth_time字段。
ApplyRecord.objects.filter(user_id=self.user_id) \.annotate(auth_time=F("time")) \.filter(auth_time_filter_range) \.values("id", "auth_time")
alias
是3.2版本的新方法,用法和annotate一样,区别是annotate会在员对象上增加一个字段保存聚合结果,而alias则不会在原对象上增加字段。Not selecting the unused value removes redundant work from the database which should result in better performance. 对性能更加友好。
order_by
Django查询默认使用Meta.order指定的字段排序,允许显式调用order_by方法重写排序规则。支持跨表排序。
Entry.objects.filter(blog__name='Beatles Blog')
Blog.objects.filter(entry__authors__name='Lennon')
支持按照外键排序,如果外键没有指定Meta.order规则,则按照外键主键排序
Entry.objects.order_by('blog')
如果Blog.Meta.order = ['name']:等价于 Entry.objects.order_by('blog__name')
否则:等价于 Entry.objects.order_by('blog__id')
支持和聚合函数联合使用
Entry.objects.order_by(Coalesce('summary', 'headline').desc())
多个order_by方法链式调用只会保留最后一个,即后者覆盖前者,
Entry.objects.order_by('headline').order_by('pub_date')
# 按照pub_date排序而不是headline
注意:排序需要耗费性能,越多的排序字段,排序逻辑越复杂,对性能影响越大。同时,表中每个外键也会默认按照对应表默认排序一次,应当减少物理外键,使用逻辑外键。
reverse
reverse方法对查询出的结果取倒序,Django不支持从尾部切片,如不支持使用[-5:]取结果集最后5个,可以使用 quertset.reverse()[:5]
另外使用reverse操作前需要对查询进行排序,否则不起作用。
distinct
去重操作。作用和 SELECT DISTINCT 一样。
注意,去重需要和排序字段保持一致,如果BLOG指定了排序方式为name,那么下列去重不会生效:
Entry.objects.order_by('blog').distinct('blog')
因为 order_by=blog__name,而distinct=blog__id
values
values(*fields)
返回一个ValuesQuerySet —— QuerySet 的一个子类,迭代时返回字典而不是模型实例对象。
每个字典表示一个对象,键对应于模型对象的属性名称。
# This list contains a Blog object.
>>> Blog.objects.filter(name__startswith='Beatles')
[<Blog: Beatles Blog>]# This list contains a dictionary.
>>> Blog.objects.filter(name__startswith='Beatles').values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]
values() 接收可选的位置参数*fields,它指定SELECT 应该限制哪些字段。如果指定字段,每个字典将只包含指定的字段键/值。如果没有指定字段,每个字典将包含数据库表中所有字段键和值。
>>> Blog.objects.values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}],
>>> Blog.objects.values('id', 'name')
[{'id': 1, 'name': 'Beatles Blog'}]
values还可以接受键值对参数,相当于隐式调用annotate。
>>> from django.db.models.functions import Lower
>>> Blog.objects.values(lower_name=Lower('name'))
<QuerySet [{'lower_name': 'beatles blog'}]>
values可以使用内置或lookups自定义方法
>>> from django.db.models import CharField
>>> from django.db.models.functions import Lower
>>> CharField.register_lookup(Lower)
>>> Blog.objects.values('name__lower')
<QuerySet [{'name__lower': 'beatles blog'}]>
values内会优先应用内聚方法, 如果你想要分组统计,则需要统计前先分组。
>>> Blog.objects.values('entry__authors', entries=Count('entry'))
<QuerySet [{'entry__authors': 1, 'entries': 20}, {'entry__authors': 1, 'entries': 13}]>>>> Blog.objects.values('entry__authors').annotate(entries=Count('entry'))
<QuerySet [{'entry__authors': 1, 'entries': 33}]>
values获取外键默认为主键ID值
>>> Entry.objects.values()
<QuerySet [{'blog_id': 1, 'headline': 'First Entry', ...}, ...]>>>> Entry.objects.values('blog')
<QuerySet [{'blog': 1}, ...]>>>> Entry.objects.values('blog_id')
<QuerySet [{'blog_id': 1}, ...]>
values_list
values_list
(*fields, flat=False, named=False)
返回指定*fields的参数元组列表
>>> Entry.objects.values_list('id', 'headline')
<QuerySet [(1, 'First entry'), ...]>
filed允许使用表达式
>>> from django.db.models.functions import Lower
>>> Entry.objects.values_list('id', Lower('headline'))
<QuerySet [(1, 'first entry'), ...]>
当只有一个参数时,允许使用flat参数
>>> Entry.objects.values_list('id').order_by('id')
<QuerySet[(1,), (2,), (3,), ...]>>>> Entry.objects.values_list('id', flat=True).order_by('id')
<QuerySet [1, 2, 3, ...]>
使用named=True参数将会把元组转换为命名空间对象,增加可读性,但是会损耗性能
# You can pass named=True to get results as a namedtuple():
>>> Entry.objects.values_list('id', 'headline', named=True)
<QuerySet [Row(id=1, headline='First entry'), ...]>
values 和 values_list 都旨在对检索性能优化:只查询具体的子集而不需要映射为模型对象,节省开销。特别的是在处理多对多和其他多值关系(例如反向外键的一对多关系)时,一个对象会返回多行:
>>> Author.objects.values_list('name', 'entry__headline')
<QuerySet [('Noam Chomsky', 'Impressions of Gaza'),('George Orwell', 'Why Socialists Do Not Believe in Fun'),('George Orwell', 'In Defence of English Cooking'),('Don Quixote', None)]>
dates
dates
(field, kind, order='ASC')
返回满足条件field的日期结果集,
field必须是 DateField 类型;
kind可以是 year | month | day | week;
order 值可以是 ASC | DESC
比如查询总共有多少个发行日
examples
>>> Entry.objects.dates('pub_date', 'year')
[datetime.date(2005, 1, 1)]
>>> Entry.objects.dates('pub_date', 'month')
[datetime.date(2005, 2, 1), datetime.date(2005, 3, 1)]
>>> Entry.objects.dates('pub_date', 'week')
[datetime.date(2005, 2, 14), datetime.date(2005, 3, 14)]
>>> Entry.objects.dates('pub_date', 'day')
[datetime.date(2005, 2, 20), datetime.date(2005, 3, 20)]
>>> Entry.objects.dates('pub_date', 'day', order='DESC')
[datetime.date(2005, 3, 20), datetime.date(2005, 2, 20)]
>>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day')
[datetime.date(2005, 3, 20)]
datetimes
datetimes
(field_name, kind, order='ASC', tzinfo=None, is_dst=None)
功能和dates类似只不过类型为datetime
field_name 必须是 DatetimeField
kind 可以是 "year"
, "month"
, "week"
, "day"
, "hour"
, "minute"
, or "second"
tzinfo
可以转换为指定时区,如果不传就是当前时区
tzinfo 时区名
none
none()
返回空的 QuerySet
>>> Entry.objects.none()
<QuerySet []>
>>> from django.db.models.query import EmptyQuerySet
>>> isinstance(Entry.objects.none(), EmptyQuerySet)
True
all
all()
返回所有查询结果,小心内存爆炸哦
Django QuerySet API 文档阅读(3):QuerySet定义(一)相关推荐
- ExtJS4 API文档阅读(四)——Data
2019独角兽企业重金招聘Python工程师标准>>> ExtJS4 API文档阅读(四)--Data 数据 Data包负责加载和保存你应用程序中的所有数据,由41个类构成,其中有三 ...
- 聚合API文档阅读帮助
聚合API文档阅读帮助 该文基于聚合云数据开放平台的API文档,目的使得开发者能够方便的快速了解我们这个API文档的结构,从而能够经行高效的开发. 该API文档总共有6个大类:国外API.国内API. ...
- 【Python】Django生成API 文档
全局配置 # DRF 全局配置 REST_FRAMEWORK = {'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema ...
- Django QuerySet API文档
在查询时发生了什么(When QuerySets are evaluated) QuerySet 可以被构造,过滤,切片,做为参数传递,这些行为都不会对数据库进行操作.只要你查询的时候才真正的操作数据 ...
- Zeal —— API文档离线阅读器
背景 在软件开发的过程中,常常需要查阅多个API文档,但网络环境等因素常常导致在线文档查看用户体验并不佳.为此,介绍一款离线的API文档阅读器,Zeal.Zeal中自配了多种API文档可供查阅,如El ...
- java smart算法_Java Restful API 文档生成工具 smart-doc
谁说生成api文档就必须要定义注解? 谁说生成接口请求和返回示例必须要在线? 用代码去探路,不断尝试更多文档交付的可能性. 如果代码有生命,为什么不换种方式和它对话! 一.背景 没有背景.就自己做自己 ...
- wordpress rest api 登录_Python构建RESTful网络服务[Django篇:生成API文档]
链接:https://pan.baidu.com/s/15Mo9adr4Iw2W-um7WK68jA 提取码:ux79 系列文章介绍 本系列文章将详细介绍将Django官方引导教程中的投票项目改写为R ...
- 【接口文档】Django restful framework中自动生成API文档
Django restful framework中自动生成API文档 一.Swagger概述 1.引言 当接口开发完成,紧接着需要编写接口文档.传统的接口文档使用Word编写,or一些接口文档管理平台 ...
- Django系列(1)-自动化生成API文档
PS: 个人深感python开发者社区氛围比安卓/ios/java差多了.不过,这也许是个机会- 前提: 本人开发环境是mac10.14.4,Python3.7.2 django-rest-swagg ...
最新文章
- 客户端与服务器的数据交互
- c语言编程中tem代表什么意思,“CTEM”是“Conventional Transmission Electron Microscopy”的缩写,意思是“常规透射电子显微镜”...
- python杂记(一)
- VS2010开发ribbon风格的程序
- m40型工业机器人_工业机器人在汽车生产中有的应用范围
- HBTS(HBOI) 2019 真实退役记
- 在我的心目中freeeim
- 去除序号(正则表达式with sublime text)
- SAP License:CO-第四夜-产品成本核算
- 自己动手实现STL:前言
- Visual C# .NET2003语言的改变
- Forking AfterBurn into Maya
- 【渝粤教育】国家开放大学2018年春季 0702-22T当代中国政治制度 参考试题
- 第九次作业(杨辉三角)
- 小小恋歌(小さな恋のうた)
- Microsoft Productivity Hub 2010 安装部署配置(三)
- Git来回切换版本的时候,pom文件变黄,每次都需要重新添加到maven以及修改后文件不生效的解决方法
- 科海思除镍树脂CH-90Na
- Django(一)简单的个人博客搭建实战
- NoticeBar 通知栏组件,封装好的可直接使用
热门文章
- 【开发工具】IDEA生成序列号serialVersionUID快捷键
- “闪送模式”定义即时配送市场,C端为何独爱“一对一”?
- Python 安装及运行方式
- 微信小程序跳一跳java代码_安卓版微信小程序跳一跳辅助
- 打开软件出现应用程序无法正常启动(0xc0000006)的解决方法
- 其实苹果手机辨别真假这么简单!查看桌面1个图标,就能轻松分辨
- 兄弟mfc 7340 加墨粉
- Win10网络102错误代码该怎么办?360浏览器网络连接错误 错误代码 102的解决方法
- Math.round(); 四舍五入下取整
- 【STM32调试(三)】采集bmp图像保存在SD卡