Django QuerySet API 整理
(译自官方文档)
以下操作会真正操作数据库:
- Iteration:在遍历对象时就会执行数据库操作
- Slicing:对与一个未查询的 QuerySet 切片就会返回另一个未查询的 QuerySet 。使用参数 step参数时会执行数据库操作
- Picking/Caching:参见 Picking QuerySet
- repr():调用该方法时查询会被运行,并可以立即看到查询结果(命令行常用)
- len():返回查询结果列表的长度。运行时执行数据库操作,使用 count()会更加高效
- list():再转化为列表时会执行数据库操作,且占用大量内存。而遍历 QuerySet 时仅使用某个对象时才加载至内存中
Picking QuerySet
| import pickle | 
QuerySet API
- filter(**kwargs):根据筛选条件返回相匹配的对象。参见 Filed lookups
- exclued(**kwargs):根据筛选条件返回不匹配的对象。
| Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello') | 
| SELECT ... | 
- annotate(*args,**kwargs):为 QuerySet 中的每个对象添加注解(可以理解为辅助计算列),具体的函数参见 Aggregation Functions
| q = Blog.objects.annotate(number_of_entries=Count('entry')) | 
- order_by(*fileds):默认情况下,QuerySet 返回的查询结果以 Model 类的 Meta 设置所提供的 ordering项中定义的排序元组来排序。可以使用order_by进行覆盖。通过设置 QuerySet.ordered 属性,可以决定某个查询是否可排序
| # 🌰:以 pub_date 升序,再以 headline 倒序,默认倒序 | 
- reverse():对查询结果进行反向排序
| # 得到查询结果中最后五个对象 | 
- distinct():返回一个新的 QuerySet ,在执行查询时使用 select distinct. 默认情况下,QuerySet 会自动剔除重复的记录,但是在多表查询时,可能会用到 Distinct(慎用)
- values(*fields):返回一个 ValuesQuerySet ,运行后得到的不是 Model 的实例话对象,而是一个可迭代的字典序列
| # This list contains a Blog object. | 
- values_list(*fields):与 values() 类似,不过返回的是元组序列
| Entry.objects.values_list('id', 'headline') | 
- dates(field , kind , order=’ASC’):返回一个DateQuerySet,提取 QuerySet 查询中所包含的日期,组成一个新的 datetime.date 对象列表
| Entry.objects.dates('pub_date', 'year') | 
- datetimes(field , kind , order=’ASC’):返回一个 DateTimeQuerySet ,组成一个新的 datetime.datetime 对象列表
- none():返回一个 EmptyQuerySet ,在运行时只返回一个空列表。适用于你要返回一个空列表,但调用者却需要接收一个 QuerySet 对象。
| Entry.objects.none() | 
- all():返回当前 QuerySet 但一份拷贝。当 QuerySet 运行后,会缓存查询结果,如果数据库发生了改变,调用 all() 可以更新查询
- select_related():返回一个 QuerySet ,在执行查询时进口可能深入的遍历外键关系,再查询后再使用外键关系获取关联对象时不会再读取数据库(通过库内 Join 进行查询)
- prefetch_related():与 select_related() 类似,但是是分别查询每个表,然后用 Python 处理他们之间的关系
| from django.db import models | 
- extra(select=None,where=None,params=None,tables=None,order_by=None,select_params=None)
 extra() 可以修改 QuerySet ,能在生成的SQL语句中注入新的子句。但应尽量避免写 extra ,因为违背了 DRY 原则
- defer(*field):将不想载入但字段传给 defer() 方法,可以做到延后载入
| Entry.objects.defer("lede", "body") | 
- only(*field):和 defer() 作用相反,立即载入可以使用 only()
| Person.objects.defer("age", "biography") | 
- using(alias):切换数据库,参数是数据库的alias
| # queries the database with the 'default' alias. | 
- select_for_update(nowait=False):返回queryset,并将需要更新的行锁定,类似于SELECT … FOR UPDATE的操作
| entries = Entry.objects.select_for_update().filter(author=request.user) | 
- raw(raw_query, params=None, translations=None):执行 Raw SQL 查询
不返回查询的方法
这些方法不使用缓存,他们在运行时是直接读取数据库的。
- get(**kwargs):返回与筛选条件相匹配的对象。返回对象超过一个,抛出 MultipleObjectsReturned 异常,没有返回对象返回 DoesNotExist 异常
| # DoesNotExist 异常继承自 django.core.exceptions.ObjectDoesNotExist,可以直接截获 DoesNotExist 异常 | 
- create(**kwargs):创建对象并保存
| # 以下操作等效 | 
- get_or_create(default=None,**kwargs):根据筛选条件查询对象,若不存在就创建一个
| # 以下代码效果相同,知识第一种过于臃肿 | 
- update_or_create(defaults=None,**kwargs):与 get_or_create() 类似
| try: | 
- bulk_create(objs,batch_size=None):批量创建
| Entry.objects.bulk_create([ | 
- count():返回数据库中匹配查询的对象数量,不会抛出任何异常
- in_bulk(id_list):接收一个主键值列表,然后根据每个主键值所其对应的对象,返回一个主键值与对象的映射字典
| Blog.objects.in_bulk([1]) | 
- iterator():运行查询,根据结果返回一个迭代器。分多次对数据实例化,用到时才会实例化。使用迭代器效率更高,节省内存
- latest(field_name=None):根据时间字段 field_name 得到最新的对象
| Entry.objects.latest('pub_date') | 
- earliest(field_name=None):根据时间字段 field_name 得到最旧(早)的对象 
- first():排序后对第一个对象 - p = Article.objects.order_by('title', 'pub_date').first() 
- last():类似于 first() 
- aggregate(*args, **kwargs):通过对 QuerySet 进行计算,返回一个聚合值的字典。 aggregate() 中每个参数都指定一个包含在字典中的返回值。 
| from django.db.models import Count | 
- exists():查询是否有值,返回布尔值
- update():更新
- delete():删除
字段筛选条件(Field Lookups)
字段筛选条件决定了你如何构造 SQL 语句中的 WHERE 从句。它们被指定为 QuerySet 中 filter(),exclude() 和 get() 方法的关键字参数。
- exact():精确匹配,指定为 None 值会翻译为 SQL 中对 Null
| Entry.objects.get(id__exact=14) | 
- iexact():忽略大小写的匹配,SQLite 对 Unicode 字符串,无法做忽略大小写的匹配。
| Blog.objects.get(name__iexact='beatles blog') | 
- contains():大小写敏感的包含匹配
| Entry.objects.get(headline__contains='Lennon') | 
- icontains():忽略大小写敏感的包含匹配
| Entry.objects.get(headline__icontains='Lennon') | 
- in:是否在给定的列表中
| Entry.objects.filter(id__in=[1, 3, 4]) | 
- gt:大于
- gte:大于等于
- lt:小于
- lte:小于等于
- startswith:大小写敏感的以**开头
- istartswith:忽略大小写的以**开头
- endswith:大小写敏感的以**结尾
- iendswith:忽略大小写的以**结尾
- range:包含的范围,类似 SQL 中的 BETWEEN
| import datetime | 
- year:对日期/时间字段精确匹配年份,年份用四位数字表示
| Entry.objects.filter(pub_date__year=2005) | 
等价于SQL:
| SELECT ... WHERE EXTRACT('year' FROM pub_date) = '2005'; | 
- month:对日期/时间字段精确匹配月份
- day:对日期/时间字段精确匹配日期
- week_day:对日期/时间字段精确匹配周数
- hour:对日期/时间字段精确匹配小时
- minute:对日期/时间字段精确匹配分钟
- second:对日期/时间字段精确匹配秒
- isnull:根据字段是否为空筛选数据
| Entry.objects.filter(pub_date__isnull=True) | 
| SELECT ... WHERE pub_date IS NULL; | 
- search:利用全文索引做全文搜索,与 contains 类似,但使用全文索引会更快
| Entry.objects.filter(headline__search="+Django -jazz Python") | 
- regex:大小写敏感的正则表达式匹配
| Entry.objects.get(title__regex=r'^(An?|The) +') | 
- iregex:忽略大小写的正则表达式匹配
聚合函式
- avg:__avg ,返回所给字段的平均值 
- count:__count ,返回所给关联字段的 model 数量 
- max:__max ,返回所给字段数据的最大值 
- min:__min , 返回所给字段数据的最小值 
- strdev:__stddev ,返回所给字段的标准差,sample=True 返回一个样本偏差值 
- sum:__sum ,计算所给字段的和 
- variance:__variance ,计算所给字段的标准方差,sample=True 返回样本方差