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()指定补充的字段集可以导致更简单的代码。

   假设您有一个包含字段nameagebiography的模型。以下两个查询集是相同的,就延迟字段而言:

>>>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_psycopg2oracle 和 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(),只是返回的是查询集中最后一个对象。

 

未完待续  

 

  

posted @ 2017-05-20 08:22  Vincen_shen  阅读(179)  评论(0编辑  收藏  举报