QuerySet API
QuerySet有很多API接口,比如常用的Iterable、exists()、len()、count()、切片、pickling、cache、repr()、list().
iterable:
QuerySet是可迭代的,它在首次迭代查询集时执行实际的数据库查询。例如下面的语句会将数据库中所有Entry 的headline 打印出来:
for obj in Entry.objects.all(): print(obj.name)
注意:不要使用上面的语句来验证在数据库中是否至少存在一条记录。使用 exists()方法更高效。
exists()
如果QuerySet 包含任何结果,则返回True,否则返回False。
查找具有唯一性字段(例如primary_key)的模型是否在一个QuerySet 中的最高效的方法是:
entry = Entry.objects.get(pk=123)
if some_queryset.filter(pk=entry.pk).exists():
print("Entry contained in queryset")
若要查找一个QuerySet 是否包含任何元素:
if some_queryset.exists():
print("There is at least one object in some_queryset")
将快于:
if some_queryset:
print("There is at least one object in some_queryset")
filter
- 返回一个新的QuerySet,包含与给定的查询参数匹配的对象。
exclude
返回一个新的QuerySet,它包含不满足给定的查找参数的对象。
annotate
使用提供的查询表达式 Annotate QuerySet中的每个对象。查询表达式可以是一个简单的值、模型(或关联模型)字段的一个引用或对查询集中的对象一个聚合函数(平均值、和等)。annotate() 的每个参数都是一个annotation,它将添加到返回的QuerySet的每个对象中。
order_by
默认情况下, QuerySet根据模型Meta类的ordering选项排序。你可以使用order_by方法给每个QuerySet 指定特定的排序。
Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')
上面的结果将按照pub_date 降序排序,然后再按照headline 升序排序。"-pub_date" 前面的负号表示降序排序。隐式的是升序排序。若要随机排序,请使用"?",像这样:
Entry.objects.order_by('?')
通过关联字段排序QuerySet 还能够不用带来JOIN 产生的花费,方法是引用关联字段的_id:
# No Join
Entry.objects.order_by('blog_id')
# Join
Entry.objects.order_by('blog__id')
你还可以通过调用表达式的asc() 或者desc()
reverse()
反向排序QuerySet 中返回的元素。第二次调用reverse() 将恢复到原有的排序。
注意: reverse() 应该只在一个已经定义排序的QuerySet 上调用(例如,在一个定义了默认排序的模型上,或者使用order_by() 的时候)。如果QuerySet 没有定义排序,调用reverse() 将不会有任何效果(在调用reverse() 之前没有定义排序,那么调用之后仍保持没有定义)。
distinct()
返回一个在SQL 查询中使用SELECT DISTINCT 的新QuerySet。它将去除查询结果中重复的行。
Select_related(*fields)
返回一个QuerySet,当执行它的查询时它沿着外键关系查询关联的对象的数据。它会生成一个复杂的查询并引起性能的损耗,但是在以后使用外键关系时将不需要数据库查询。
defer(*fields)
在一些复杂的数据建模情况下,您的模型可能包含大量字段,其中一些可能包含大量数据(例如,文本字段),或者需要昂贵的处理来将它们转换为Python对象。如果您在某些情况下使用查询集的结果,当您最初获取数据时不知道是否需要这些特定字段,可以告诉Django不要从数据库中检索它们。
这是通过传递字段名称不加载到defer():
Entry.objects.defer("headline", "body")
only(*fields)
only()方法或多或少与defer()相反。您调用它时,应该在检索模型时延迟的字段。如果你有一个模型几乎所有的字段需要延迟,使用only()指定补充的字段集可以导致更简单的代码。
假设您有一个包含字段name, age和biography的模型。以下两个查询集是相同的,就延迟字段而言:
>>>Person.objects.defer("age", "biography") >>>Person.objects.only("name")
select_for_update(nowait=False)
返回一个 queryset ,会锁定相关行直到事务结束。在支持的数据库上面产生一个SELECT ... FORUPDATE语句
>>>entries = Entry.objects.select_for_update().filter(author=request.user)
所有匹配的行将被锁定,直到事务结束。这意味着可以通过锁防止数据被其它事务修改。
一般情况下如果其他事务锁定了相关行,那么本查询将被阻塞,直到锁被释放。如果这不是你想要的行为,请使用select_for_update(nowait=True). 这将使查询不阻塞。
目前,postgresql_psycopg2, oracle 和 mysql 数据库后端支持 select_for_update().但是 MySQL 不支持 nowait 参数。显然,用户应该检查后端的支持情况。
当在不支持nowait功能的数据库后端(例如 MySql) 使用nowait=True 参数调用 select_for_update() 时将引发DatabaseError 异常. 这是防止意外造成代码被阻塞。
count()
返回在数据库中对应的 QuerySet.对象的个数。count() 永远不会引发异常。
iterator()
- 返回一个迭代器(参见 PEP 234)。QuerySet通常在内部缓存其结果,以便在重复计算是不会导致额外的查询。相反,iterator()将直接读取结果,而不在QuerySet级别执行任何缓存(内部,默认迭代器调用iterator()并高速缓存返回值)。对于返回大量只需要访问一次的对象的QuerySet,这可以带来更好的性能和显着减少内存。
latest(field)
使用作为日期字段提供的field_name,按日期返回表中的最新对象。 此示例根据pub_date字段返回表中的最新条目:
Entry.objects.latest('pub_date')
first()
- 返回结果集的第一个对象, 当没有找到时返回None.如果 QuerySet 没有设置排序,则将会自动按主键进行排序
>>>p = Article.objects.order_by('title', 'pub_date').first()
等于:
try: p = Article.objects.order_by('title', 'pub_date')[0] except IndexError: p = None
last()
- 工作方式类似first(),只是返回的是查询集中最后一个对象。
未完待续