QuerySet API参考

本文档描述了QuerySet API的详细信息。 它建立在modeldatabase query指南的基础上,所以在阅读本文档之前,你也许需要首先阅读这两部分的文档。

本文档将通篇使用在database query guide中用到的example Weblog models

QuerySet何时求值

本质上,可以创建、过滤、切片和传递QuerySet而不用真实操作数据库。 在你对查询集做求值之前,不会发生任何实际的数据库操作。

你可以使用下列方法对QuerySet求值:

  • Iteration. QuerySet是可迭代的,它在首次迭代查询集时执行实际的数据库查询。 例如, 下面的语句会将数据库中所有Entry 的headline 打印出来:

    for e in Entry.objects.all():
        print(e.headline)
    

    注意:不要使用上面的语句来验证在数据库中是否至少存在一条记录。 使用 exists()方法更高效。

  • Slicing. 正如在Limiting QuerySets中解释的那样, 可以使用Python 的序列切片语法对一个QuerySet进行分片。 一个未求值的QuerySet进行切片通常返回另一个未求值的QuerySet,但是如果你使用切片的”step“参数,Django 将执行数据库查询并返回一个列表。 对一个已经求值的QuerySet进行切片将返回一个列表。

    还要注意,虽然对未求值的QuerySet进行切片返回另一个未求值的QuerySet,但是却不可以进一步修改它了(例如,添加更多的Filter,或者修改排序的方式),因为这将不太好翻译成SQL而且含义也不清晰。

  • Pickling/Caching. 序列化查询集的细节参见下面一节。 本节提到它的目的是强调序列化将读取数据库。

  • repr()。 当对QuerySet调用repr() 时,将对它求值。 这是为了在Python 交互式解释器中使用的方便,这样你可以在交互式使用这个API 时立即看到结果。

  • len()。 当你对QuerySet调用len() 时, 将对它求值。 正如你期望的那样,返回一个查询结果集的长度。

    注意: 如果你确定只需要获取结果集的数量 (而不需要实际的查询结果), 那么在数据库级别使用SQL的SELECT COUNT(*)语句来处理计数会更有效率. 为此,Django 提供了 一个count() 方法.

  • list()。 QuerySet调用list() 将强制对它求值。 像这样:

    entry_list = list(Entry.objects.all())
    
  • bool()。 测试一个QuerySet的布尔值,例如使用bool()orand 或者if 语句将导致查询集的执行。 如果至少有一个记录,则QuerySetTrue,否则为False 像这样:

    if Entry.objects.filter(headline="Test"):
       print("There is at least one Entry with the headline Test")
    

    注:如果你需要知道是否存在至少一条记录(而不需要真实的对象),使用 exists() 将更加高效。

Pickling QuerySet

如果你pickle一个QuerySet,它将在Pickle 之前强制将所有的结果加载到内存中。 Pickle 通常用于缓存之前,并且当缓存的查询集重新加载时,你希望结果已经存在随时准备使用(从数据库读取耗费时间,就失去了缓存的目的)。 这意味着当你UnpickleQuerySet时,它包含Pickle 时的结果,而不是当前数据库中的结果。

如果此后你只想Pickle 必要的信息来从数据库重新创建QuerySet,可以PickleQuerySetquery 属性。 然后你可以使用类似下面的代码重新创建原始的QuerySet(不用加载任何结果):

>>> import pickle
>>> query = pickle.loads(s)     # Assuming 's' is the pickled string.
>>> qs = MyModel.objects.all()
>>> qs.query = query            # Restore the original 'query'.

query 是一个不透明的对象。 它表示查询的内部构造,不属于公开的API。 然而,这里讲到的Pickle 和Unpickle 这个属性的内容是安全的(和完全支持的)。

不可以在不同版本之间共享Pickle 的结果

QuerySets的Pickle 只能用于生成它们的Django 版本中。 如果你使用Django 的版本N 生成一个Pickle,不保证这个Pickle 在Django 的版本N+1 中可以读取。 Pickle 不可用于归档的长期策略。

因为Pickle 兼容性的错误很难诊断例如产生损坏的对象,当你试图Unpickle 的查询集与Pickle 时的Django 版本不同,将引发一个RuntimeWarning

QuerySet API

下面是对于QuerySet的正式定义:

class QuerySet(model=None, query=None, using=None)[source]

通常你在使用QuerySet时会以chaining filters 来使用。 为了让这个能工作,大部分QuerySet 方法返回新的QuerySet。 这些方法在本节将详细讲述。

QuerySet 类具有两个公有属性用于内省:

ordered

如果QuerySet 是排好序的则为True —— 例如有一个order_by() 子句或者模型有默认的排序。 否则为False .

db

如果现在执行,则返回将使用的数据库。

QuerySet 存在query 参数是为了让具有特殊查询用途的子类如GeoQuerySet 可以重新构造内部的查询状态。 这个参数的值是查询状态的不透明的表示,不是一个公开的API。 简而言之:如果你有疑问,那么你实际上不需要使用它。

返回新的QuerySet的方法

Django 提供了一系列 的QuerySet筛选方法,用于改变 QuerySet 返回的结果类型或者SQL查询执行的方式。

filter()

filter(**kwargs)

返回一个新的QuerySet,它包含满足查询参数的对象。

查找的参数(**kwargs)应该满足下文字段查找中的格式。 在底层的SQL 语句中,多个参数通过AND 连接。

如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q objects

exclude()

exclude(**kwargs)

返回一个新的QuerySet,它包含满足给定的查找参数的对象。

查找的参数(**kwargs)应该满足下文字段查找中的格式。 在底层的SQL 语句中,多个参数通过AND 连接,然后所有的内容放入NOT() 中。

下面的示例排除所有pub_date 晚于2005-1-3 且headline 为“Hello” 的记录:

Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')

用SQL 语句,它等同于:

SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')

下面的示例排除所有pub_date 晚于2005-1-3 或者headline 为“Hello” 的记录:

Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')

用SQL 语句,它等同于:

SELECT ...
WHERE NOT pub_date > '2005-1-3'
AND NOT headline = 'Hello'

注意,第二个示例更严格。

如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q objects

annotate()

annotate(*args, **kwargs)

使用提供的查询表达式Annotate查询集中的每个对象。 表达式可以是简单的值、模型(或任何关联模型)上的字段的引用或者聚合表达式(平均值、总和等), 它们已经在与QuerySet中的对象相关的对象上进行了计算。

annotate()的每个参数都是一个annotation,将添加到返回的QuerySet中的每个对象。

Django提供的聚合函数在下文的聚合函数文档中讲述。

关键字参数指定的Annotation将使用关键字作为Annotation的别名。 匿名的参数的别名将基于聚合函数的名称和模型的字段生成。 只有引用单个字段的聚合表达式才可以使用匿名参数。 其它所有形式都必须用关键字参数。

例如,如果你正在操作一个Blog列表,你可能想知道每个Blog有多少Entry:

>>> from django.db.models import Count
>>> q = Blog.objects.annotate(Count('entry'))
# The name of the first blog
>>> q[0].name
'Blogasaurus'
# The number of entries on the first blog
>>> q[0].entry__count
42

Blog模型本身没有定义entry__count属性,通过使用一个关键字参数来指定聚合函数,你可以控制Annotation的名称:

>>> q = Blog.objects.annotate(number_of_entries=Count('entry'))
# The number of entries on the first blog, using the name provided
>>> q[0].number_of_entries
42

聚合的深入讨论,参见聚合主题的指南

order_by()

order_by(*fields)

默认情况下,Meta 根据模型ordering 类的QuerySet 选项排序。 你可以使用QuerySet 方法给每个order_by 指定特定的排序。

例如:

Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')

上面的结果将按照pub_date 降序排序,然后再按照headline 升序排序。 "-pub_date"前面的负号表示降序顺序。 升序是隐含的。 要随机订购,请使用"?",如下所示:

Entry.objects.order_by('?')

注:order_by('?') 查询可能耗费资源且很慢,这取决于使用的数据库。

若要按照另外一个模型中的字段排序,可以使用查询关联模型时的语法。 即通过字段的名称后面跟上两个下划线(__),再跟上新模型中的字段的名称,直至你希望连接的模型。 像这样:

Entry.objects.order_by('blog__name', 'headline')

如果排序的字段与另外一个模型关联,Django 将使用关联的模型的默认排序,或者如果没有指定Meta.ordering 将通过关联的模型的主键排序。 例如,因为Blog 模型没有指定默认的排序:

Entry.objects.order_by('blog')

...与以下相同:

Entry.objects.order_by('blog__id')

如果Blog 设置ordering = ['name'],那么第一个QuerySet 将等同于:

Entry.objects.order_by('blog__name')

你还可以通过调用表达式的desc() 或者asc(),根据query expressions排序:

Entry.objects.order_by(Coalesce('summary', 'headline').desc())

如果你还用到distinct(),在根据关联模型中的字段排序时要小心。 distinct() 中有一个备注讲述关联模型的排序如何对结果产生影响。

指定一个多值字段来排序结果(例如,一个ManyToManyField 字段或者ForeignKey 字段的反向关联)。

考虑下面的情况:

class Event(Model):
   parent = models.ForeignKey(
       'self',
       on_delete=models.CASCADE,
       related_name='children',
   )
   date = models.DateField()

Event.objects.order_by('children__date')

在这里,每个Event可能有多个排序数据;具有多个children的每个Event将被多次返回到order_by()创建的新的QuerySet中。 换句话说, 用 order_by()方法对 QuerySet对象进行操作会返回一个扩大版的新QuerySet对象——新增的条目也许并没有什么卵用,你也用不着它们。

因此,当你使用多值字段对结果进行排序时要格外小心。 如果,您可以确保每个订单项只有一个订购数据,这种方法不会出现问题。 如果不确定,请确保结果是你期望的。

没有方法指定排序是否考虑大小写。 对于大小写的敏感性,Django 将根据数据库中的排序方式排序结果。

你可以通过Lower将一个字段转换为小写来排序,它将达到大小写一致的排序:

Entry.objects.order_by(Lower('headline').desc())

如果你不想对查询做任何排序,即使是默认的排序,可以不带参数调用order_by()

你可以通过检查QuerySet.ordered 属性来知道查询是否是排序的,如果True 有任何方式的排序它将为QuerySet

每个order_by() 都将清除前面的任何排序。 例如,下面的查询将按照pub_date 排序,而不是headline

Entry.objects.order_by('headline').order_by('pub_date')

警告

排序不是没有开销的操作。 添加到排序中的每个字段都将带来数据库的开销。 添加的每个外键也都将隐式包含进它的默认排序。

如果查询没有指定的顺序,则会以未指定的顺序从数据库返回结果。 仅当通过唯一标识结果中的每个对象的一组字段排序时,才能保证特定的排序。 例如,如果name字段不唯一,则由其排序不会保证具有相同名称的对象总是以相同的顺序显示。

reverse()

reverse()

reverse() 方法反向排序QuerySet 中返回的元素。 第二次调用reverse() 将恢复到原有的排序。

如要获取QuerySet 中最后五个元素,你可以这样做:

my_queryset.reverse()[:5]

注意,这与Python 中从一个序列的末尾进行切片有点不一样。 上面的例子将首先返回最后一个元素,然后是倒数第二个元素,以此类推。 如果我们有一个Python 序列,当我们查看seq[-5:] 时,我们将一下子得到倒数五个元素。 Django 不支持这种访问模型(从末尾进行切片),因为它不可能利用SQL 高效地实现。

同时还要注意,QuerySet 应该只在一个已经定义排序的reverse() 上调用(例如,在一个定义了默认排序的模型上,或者使用order_by() 的时候)。 如果reverse() 没有定义排序,调用reverse() 将不会有任何效果(在调用QuerySet 之前没有定义排序,那么调用之后仍保持没有定义)。

distinct()

distinct(*fields)

返回一个在SQL 查询中使用SELECT DISTINCT 的新QuerySet 它将去除查询结果中重复的行。

默认情况下,QuerySet 不会去除重复的行。 在实际应用中,这一般不是个问题,因为像Blog.objects.all() 这样的简单查询不会引入重复的行。 但是,如果查询跨越多张表,当对QuerySet 求值时就可能得到重复的结果。 这时候你应该使用distinct()

order_by() 调用中的任何字段都将包含在SQL 的 SELECT 列中。 distinct() 一起使用时可能导致预计不到的结果。 如果你根据关联模型的字段排序,这些fields将添加到查询的字段中,它们可能产生本应该是唯一的重复的行。 因为多余的列没有出现在返回的结果中(它们只是为了支持排序),有时候看上去像是返回了不明确的结果。

类似地,如果您使用values()查询来限制所选择的列,则仍然会涉及任何order_by()(或默认模型排序)影响结果的唯一性。

这里的约束是,如果你使用的是distinct(),请注意相关模型的排序。 类似地,当一起使用distinct()values()时,请注意字段在不在values()

在PostgreSQL上,您可以传递位置参数(*fields),以便指定DISTINCT应该应用的字段的名称。 这转换为SELECT DISTINCT ON SQL查询。 这里有区别。 对于正常的distinct()调用,数据库在确定哪些行不同时比较每行中的每个字段。 对于具有指定字段名称的distinct()调用,数据库将仅比较指定的字段名称。

当你指定字段名称时,必须distinct()中提供QuerySet,而且order_by()中的字段必须以order_by()中的字段相同开始并且顺序相同。

例如,SELECT DISTINCT ON (a)a中的每个值。 如果你没有指定一个顺序,你会得到一个任意的行。

示例(除第一个示例外,其他示例都只能在PostgreSQL 上工作):

>>> Author.objects.distinct()
[...]

>>> Entry.objects.order_by('pub_date').distinct('pub_date')
[...]

>>> Entry.objects.order_by('blog').distinct('blog')
[...]

>>> Entry.objects.order_by('author', 'pub_date').distinct('author', 'pub_date')
[...]

>>> Entry.objects.order_by('blog__name', 'mod_date').distinct('blog__name', 'mod_date')
[...]

>>> Entry.objects.order_by('author', 'pub_date').distinct('author')
[...]

请记住,order_by()使用已定义的任何默认相关模型排序。 您可能需要通过关系_id或引用字段显式排序,以确保DISTINCT ONORDER BY子句的开头。 例如,如果Blog模型通过name定义ordering

Entry.objects.order_by('blog').distinct('blog')

…wouldn’t work because the query would be ordered by blog__name thus mismatching the DISTINCT ON expression. 你必须按照关系_id字段(在这种情况下为blog__pk)或引用的(blog_id)显式排序来确保两个表达式都匹配。

values()

values(*fields, **expressions)

返回一个QuerySet,当迭代它时,返回字典而不是模型实例。

每个字典表示一个对象,键对应于模型对象的属性名称。

下面的例子将values() 与普通的模型对象进行比较:

# This list contains a Blog object.
>>> Blog.objects.filter(name__startswith='Beatles')
<QuerySet [<Blog: Beatles Blog>]>

# This list contains a dictionary.
>>> Blog.objects.filter(name__startswith='Beatles').values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>

SELECT 接收可选的位置参数*fields,它指定values() 应该限制哪些字段。 如果指定字段,每个字典将只包含指定的字段的键/值。 如果没有指定字段,每个字典将包含数据库表中所有字段的键和值。

例如:

>>> Blog.objects.values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
>>> Blog.objects.values('id', 'name')
<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>

values()方法还采用可选的关键字参数**expressions,这些参数传递给annotate()

>>> from django.db.models.functions import Lower
>>> Blog.objects.values(lower_name=Lower('name'))
<QuerySet [{'lower_name': 'beatles blog'}]>

values()子句中的聚合应用于相同values()子句中的其他参数之前。 如果您需要按另一个值分组,请将其添加到较早的values()子句中。 像这样:

>>> from django.db.models import Count
>>> Blog.objects.values('author', entries=Count('entry'))
<QuerySet [{'author': 1, 'entries': 20}, {'author': 1, 'entries': 13}]>
>>> Blog.objects.values('author').annotate(entries=Count('entry'))
<QuerySet [{'author': 1, 'entries': 33}]>

值得注意的几点:

  • 如果你有一个字段foo 是一个ForeignKey,默认的foo_id 调用返回的字典将有一个叫做foo 的键,因为这是保存实际的值的那个隐藏的模型属性的名称(values() 属性引用关联的模型)。 当你调用foo_id 并传递字段的名称,传递foovalues() 都可以,得到的结果是相同的(字典的键会与你传递的字段名匹配)。

    像这样:

    >>> 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()distinct() 一起使用时,注意排序可能影响最终的结果。 详细信息参见distinct() 中的备注。

  • 如果values() 子句位于extra() 调用之后,extra() 中的select 参数定义的字段必须显式包含在values() 调用中。 values() 调用后面的extra() 调用将忽略选择的额外的字段。

  • values() 之后调用only()defer() 不太合理,所以将引发一个NotImplementedError

当您知道您只需要少量可用字段中的值时,这是非常有用的,您将不需要模型实例对象的功能。 只选择用到的字段当然更高效。

最后,请注意,您可以调用filter()order_by()等。 values()调用之后,这意味着这两个调用是相同的:

Blog.objects.values().order_by('id')
Blog.objects.order_by('id').values()

Django 的作者喜欢将影响SQL 的方法放在前面,然后放置影响输出的方法(例如values()),但是实际上无所谓。 这是卖弄你个性的好机会。

你可以通过ManyToManyFieldForeignKeyOneToOneField 属性反向引用关联的模型的字段:

>>> Blog.objects.values('name', 'entry__headline')
<QuerySet [{'name': 'My blog', 'entry__headline': 'An entry'},
     {'name': 'My blog', 'entry__headline': 'Another entry'}, ...]>

警告

因为ManyToManyField 字段和反向关联可能有多个关联的行,包含它们可能导致结果集的倍数放大。 如果你在values() 查询中包含多个这样的字段将更加明显,这种情况下将返回所有可能的组合。

在Django更改1.11:

支持**expressions

values_list()

values_list(*fields, flat=False)

values() 类似,只是在迭代时返回的是元组而不是字典。 每个元组包含传递给values_list()调用的相应字段或表达式的值,因此第一个项目是第一个字段等。 像这样:

>>> Entry.objects.values_list('id', 'headline')
<QuerySet [(1, 'First entry'), ...]>
>>> from django.db.models.functions import Lower
>>> Entry.objects.values_list('id', Lower('headline'))
<QuerySet [(1, 'first entry'), ...]>

如果只传递一个字段,你还可以传递flat 参数。 如果为True,它表示返回的结果为单个值而不是元组。 一个例子会让它们的区别更加清晰:

>>> 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, ...]>

如果有多个字段,传递flat 将发生错误。

如果你不传递任何值给values_list(),它将返回模型中的所有字段,以它们在模型中定义的顺序。

常见的需求是获取某个模型实例的特定字段值。 为了实现这一点,使用values_list(),然后使用get()调用:

>>> Entry.objects.values_list('headline', flat=True).get(pk=1)
'First entry'

values()values_list()都用于特定用例的优化:检索数据子集,而无需创建模型实例的开销。 这个比喻在处理多对多和其他多值关系(例如反向外键的一对多关系)时分歧,因为“一行一对象”的假设不成立。

例如,注意通过ManyToManyField进行查询时的行为:

>>> 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)]>

具有多个条目的作者多次出现,没有任何条目的作者对条目标题具有None

类似地,当查询反向外键时,对于没有任何作者的条目,出现None

>>> Entry.objects.values_list('authors')
<QuerySet [('Noam Chomsky',), ('George Orwell',), (None,)]>
在Django更改1.11:

添加了对*fields中的表达式的支持。

dates()

dates(field, kind, order='ASC')

返回一个QuerySet,它将求值为表示QuerySet内容中特定类型的所有可用日期的datetime.date对象列表。

field应该是您的模型的DateField的名称。 kind应为"year""month""day" 结果列表中的每个datetime.date对象被“截断”到给定的type

  • "year" 返回对应该field的所有不同年份值的list。
  • "month"返回字段的所有不同年/月值的列表。
  • "day"返回字段的所有不同年/月/日值的列表。

'ASC'(默认为'ASC')应为order'DESC' 它t指定如何排序结果。

例子:

>>> 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', '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)

返回QuerySet,其计算为datetime.datetime对象的列表,表示QuerySet内容中特定种类的所有可用日期。

field_name应为模型的DateTimeField的名称。

kind应为"hour""minute""month""year""second""day" 结果列表中的每个datetime.datetime对象被“截断”到给定的type

'ASC'(默认为'ASC')应为order'DESC' 它t指定如何排序结果。

tzinfo定义在截断之前将数据时间转换到的时区。 实际上,给定的datetime具有不同的表示,这取决于使用的时区。 此参数必须是datetime.tzinfo对象。 如果它None,Django使用current time zone USE_TZFalse时,它不起作用。

此函数直接在数据库中执行时区转换。 因此,您的数据库必须能够解释tzinfo.tzname(None)的值。 这转化为以下要求:

  • SQLite:没有要求。 转换在Python中使用pytz执行(安装Django时安装)。
  • PostgreSQL:没有要求(见时区)。
  • Oracle:无要求(请参阅选择时区文件)。
  • MySQL:使用mysql_tzinfo_to_sql加载时区表。

none()

none()

调用none()将创建一个从不返回任何对象的查询集,并且在访问结果时不会执行任何查询。 qs.none()查询集是EmptyQuerySet的一个实例。

例子:

>>> Entry.objects.none()
<QuerySet []>
>>> from django.db.models.query import EmptyQuerySet
>>> isinstance(Entry.objects.none(), EmptyQuerySet)
True

all()

all()

返回当前QuerySet(或QuerySet 子类) 的副本 它可以用于在你希望传递一个模型管理器或QuerySet 并对结果做进一步过滤的情况。 不管对哪一种对象调用all(),你都将获得一个可以工作的QuerySet

当对QuerySet进行evaluated时,它通常会缓存其结果。 如果数据库中的数据在QuerySet求值之后可能已经改变,你可以通过在以前求值过的all()上调用相同的QuerySet 查询以获得更新后的结果。

union()

union(*other_qs, all=False)
Django中的新功能1.11。

使用SQL的UNION运算符组合两个或更多个QuerySet的结果。例如:

>>> qs1.union(qs2, qs3)

默认情况下,UNION操作符仅选择不同的值。 要允许重复值,请使用all=True参数。

union()intersection()difference()返回第一个QuerySet即使参数是其他模型的QuerySet 只要SELECT列表在所有QuerySet中是相同的,传递不同的模型就起作用(至少在类型中,名称不重要,只要在相同的顺序)。

另外,只有LIMITOFFSETCOUNT(*)ORDER BY (即切片,count()order_by())在结果QuerySet上被允许。 此外,数据库对组合查询中允许的操作设置了限制。 例如,大多数数据库不允许组合查询中的LIMITOFFSET

在Django更改1.11.4:

已添加COUNT(*)个支持。

intersection()

intersection(*other_qs)
Django中的新功能1.11。

使用SQL的INTERSECT运算符返回两个或更多个QuerySet的共享元素。例如:

>>> qs1.intersection(qs2, qs3)

有关某些限制,请参阅union()

difference()

difference(*other_qs)
Django中的新功能1.11。

使用SQL的EXCEPT运算符只保留QuerySet中的元素,但不保留其他QuerySet中的元素。例如:

>>> qs1.difference(qs2, qs3)

有关某些限制,请参阅union()

extra()

extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)

有些情况下,Django的查询语法难以简单的表达复杂的 WHERE 子句, 对于这种情况, Django 提供了 QuerySet QuerySet 修改机制 — 它能在 extra()生成的SQL从句中注入新子句

使用这种方法作为最后的手段

这是一个旧的API,我们的目标是在将来的某个时候弃用。 仅当您无法使用其他查询方法表达您的查询时才使用它。 If you do need to use it, please file a ticket using the QuerySet.extra keyword with your use case (please check the list of existing tickets first) so that we can enhance the QuerySet API to allow removing extra(). 我们不再改进或修复此方法的错误。

例如,这种使用extra()

>>> qs.extra(
...     select={'val': "select col from sometable where othercol = %s"},
...     select_params=(someparam,),
... )

相当于:

>>> qs.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))

使用RawSQL的主要好处是可以根据需要设置output_field 主要的缺点是,如果您在原始SQL中引用了查询器的某些表别名,那么Django可能会更改该别名(例如,当查询集用作另一个查询中的子查询)时。

警告

无论何时你都需要非常小心的使用extra(). 每次使用它时,您都应该转义用户可以使用params控制的任何参数,以防止SQL注入攻击。 请详细了解SQL injection protection

由于产品差异的原因,这些自定义的查询难以保障在不同的数据库之间兼容(因为你手写 SQL 代码的原因),而且违背了 DRY 原则,所以如非必要,还是尽量避免写 extra。

extra可以指定一个或多个 where,例如 select, params or tables. 这些参数都不是必须的,但是你至少要使用一个

  • select

    The select 参数可以让你在 SELECT 从句中添加其他字段信息, 它应该是一个字典,存放着属性名到 SQL 从句的映射。

    例如:

    Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
    

    结果集中每个 pub_date 对象都有一个额外的属性is_recent, 它是一个布尔值,表示 Entry对象的Entry 是否晚于 Jan. 1, 2006.

    Django 会直接在 SELECT 中加入对应的 SQL 片断,所以转换后的 SQL 如下:

    SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent
    FROM blog_entry;
    

    下一个例子是更先进的;它会执行一个子查询,为每个结果Blog对象提供一个entry_count属性,一个关联的Entry对象的整数:

    Blog.objects.extra(
        select={
            'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
        },
    )
    

    在上面这个特例中,我们要了解这个事实,就是 blog_blog 表已经存在于FROM从句中

    上面例子的结果SQL将是:

    SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count
    FROM blog_blog;
    

    要注意的是,大多数数据库需要在子句两端添加括号,而在 Django 的select从句中却无须这样。 另请注意,某些数据库后端(如某些MySQL版本)不支持子查询。

    在少数情况下,您可能希望将参数传递到extra(select=...)中的SQL片段。 为此,请使用select_params参数。 由于select_params是一个序列,并且select属性是字典,因此需要注意,以便参数与额外的选择片段正确匹配。 在这种情况下,您应该使用collections.OrderedDict作为select值,而不仅仅是普通的Python字典。

    这将工作,例如:

    Blog.objects.extra(
        select=OrderedDict([('a', '%s'), ('b', '%s')]),
        select_params=('one', 'two'))
    

    如果您需要在选择字符串中使用文本%s,请使用序列%%s

  • where / tables

    您可以使用WHERE定义显式SQL where子句 - 也许执行非显式连接。 您可以使用FROM手动将表添加到SQL tables子句。

    wheretables都接受字符串列表。 所有where参数均为“与”任何其他搜索条件。

    例如:

    Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
    

    ...(大致)翻译成以下SQL:

    SELECT * FROM blog_entry WHERE (foo='a' OR bar='a') AND (baz='a')
    

    如果您要指定已在查询中使用的表,请在使用tables参数时小心。 当您通过tables参数添加额外的表时,Django假定您希望该表包含额外的时间(如果已包括)。 这会产生一个问题,因为表名将会被赋予一个别名。 如果表在SQL语句中多次出现,则第二次和后续出现必须使用别名,以便数据库可以区分它们。 如果您指的是在额外的where参数中添加的额外表,这将导致错误。

    通常,您只需添加尚未显示在查询中的额外表。 然而,如果发生上述情况,则有几种解决方案。 首先,看看你是否可以不包括额外的表,并使用已经在查询中的一个。 如果不可能,请将extra()调用放在查询集结构的前面,以便您的表是该表的第一次使用。 最后,如果所有其他失败,请查看生成的查询并重写where添加以使用给您的额外表的别名。 每次以相同的方式构造查询集时,别名将是相同的,因此您可以依靠别名不更改。

  • order_by

    如果您需要使用通过extra()包含的一些新字段或表来对结果查询进行排序,请使用order_by参数extra()并传入一个字符串序列 。这些字符串应该是模型字段(如查询集上的正常order_by()方法),形式为extra()或您在table_name.column_name参数到select

    像这样:

    q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
    q = q.extra(order_by = ['-is_recent'])
    

    这会将False的所有项目排序到结果集的前面(Trueis_recent之前按降序排序)。

    顺便说一句,你可以对extra()进行多次调用,它会按照你的期望(每次添加新的约束)运行。

  • params

    上述where参数可以使用标准Python数据库字符串占位符 - '%s'来指示数据库引擎应自动引用的参数。 params参数是要替换的任何额外参数的列表。

    例如:

    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
    

    始终使用params而不是将值直接嵌入where,因为params会确保根据您的特定后端正确引用值。 例如,引号将被正确转义。

    Bad:

    Entry.objects.extra(where=["headline='Lennon'"])
    

    Good:

    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
    

警告

如果您正在对MySQL执行查询,请注意,MySQL的静默类型强制可能会在混合类型时导致意外的结果。 If you query on a string type column, but with an integer value, MySQL will coerce the types of all values in the table to an integer before performing the comparison. 例如,如果表包含值'def''abc',并查询WHERE mycolumn = 0,两行都将匹配。 为了防止这种情况,请在使用查询中的值之前执行正确的类型转换。

defer()

defer(*fields)

在一些复杂的数据建模情况下,你的模型可能包含大量字段,其中一些可能包含大量数据(例如文本字段),或者需要昂贵的处理来将它们转换为Python对象。 当你最初获取数据时不知道是否需要这些特定字段的情况下,如果你正在使用查询集的结果,你可以告诉Django不要从数据库中检索它们。

它通过传递字段名称到defer()实现不加载:

Entry.objects.defer("headline", "body")

具有延迟字段的查询集仍将返回模型实例。 每个延迟字段将在你访问该字段时从数据库中检索(每次只检索一个,而不是一次检索所有的延迟字段)。

你可以多次调用defer() 每个调用都向延迟集添加新字段:

# 延迟body和headline两个字段。
Entry.objects.defer("body").filter(rating=5).defer("headline")

字段添加到延迟集的顺序无关紧要。 对已经延迟的字段名称再次defer()不会有问题(该字段仍将被延迟)。

你可以使用标准的双下划线符号来分隔关联的字段,从而推迟关联模型中的字段加载(如果关联模型通过select_related()加载):

Blog.objects.select_related().defer("entry__headline", "entry__body")

如果要清除延迟字段集,请将None作为参数传递到defer()

# 立即加载所有的字段。
my_queryset.defer(None)

模型中的某些字段不会被延迟,即使你要求它们延迟。 你永远不能延迟加载主键。 如果你使用select_related()检索关联模型,则不应延迟加载从主模型连接到关联模型的关联字段,否则将导致错误。

defer()方法(及其表兄弟,only())仅适用于高级用例。 它们提供了一个优化,当你仔细分析查询并且完全了解需要什么信息,知道返回需要的字段与返回模型的全部字段之间的区别非常重要。

即使你认为你是在高级的情况下,只在当你不能在查询集加载时确定是否需要额外的字段时使用defer() 如果你经常加载和使用特定的数据子集,最好的选择是规范化模型,并将未加载的数据放入单独的模型(和数据库表)。 如果列必须由于某种原因保留在一个表中,请创建一个具有Meta.managed = false(请参阅managed attribute文档)的模型,只包含你通常需要加载和使用否则就要调用defer()的字段。 这使得你的代码对读者更加明确,稍微更快一些,并且在Python进程中消耗更少的内存。

例如,这两个模型使用相同的底层数据库表:

class CommonlyUsedModel(models.Model):
    f1 = models.CharField(max_length=10)

    class Meta:
        managed = False
        db_table = 'app_largetable'

class ManagedModel(models.Model):
    f1 = models.CharField(max_length=10)
    f2 = models.CharField(max_length=10)

    class Meta:
        db_table = 'app_largetable'

# Two equivalent QuerySets:
CommonlyUsedModel.objects.all()
ManagedModel.objects.all().defer('f2')

如果许多字段需要在非托管模型中复制,最好使用共享字段创建抽象模型,然后使非托管模型和托管模型从抽象模型继承。

当对具有延迟字段的实例调用save()时,仅保存加载的字段。 有关详细信息,请参见save()

only()

only(*fields)

only()方法或多或少与defer()相反。 你以应该在检索模型时延迟的字段调用它。 如果你有一个模型几乎所有的字段需要延迟,使用only()指定补充的字段集可以导致更简单的代码。

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

Person.objects.defer("age", "biography")
Person.objects.only("name")

每当你调用only()时,它将替换立即加载的字段集。 该方法的名称可以帮助记忆:这些字段立即加载;其余的被延迟。 因此,对only()的连续调用的结果是只有最后一次调用的字段被考虑:

# This will defer all fields except the headline.
Entry.objects.only("body", "rating").only("headline")

由于defer()以递增方式动作(向延迟列表中添加字段),因此你可以结合only()defer()调用,它们将合乎逻辑地工作:

# Final result is that everything except "headline" is deferred.
Entry.objects.only("headline", "body").defer("body")

# Final result loads headline and body immediately (only() replaces any
# existing set of fields).
Entry.objects.defer("body").only("headline", "body")

defer()文档注释中的所有注意事项也适用于only() 请谨慎使用它,只有在没有其它选择之后才使用。

使用only()并省略使用select_related()请求的字段也是错误。

当对具有延迟字段的实例调用save()时,仅保存加载的字段。 有关详细信息,请参见save()

using()

using(alias)

如果你使用多个数据库,这个方法用于控制QuerySet 将在哪个数据库上求值。 这个方法的唯一参数是数据库的别名,定义在DATABASES

像这样:

# queries the database with the 'default' alias.
>>> Entry.objects.all()

# queries the database with the 'backup' alias
>>> Entry.objects.using('backup')

select_for_update()

select_for_update(nowait=False, skip_locked=False)

返回一个锁住行直到事务结束的查询集,如果数据库支持,它将生成一个 SELECT ... FOR UPDATE 语句。

像这样:

entries = Entry.objects.select_for_update().filter(author=request.user)

所有匹配的行将被锁定,直到事务结束。这意味着可以通过锁防止数据被其它事务修改。

一般情况下如果其他事务锁定了相关行,那么本查询将被阻塞,直到锁被释放。 如果这不是你想要的行为,请使用select_for_update(nowait=True). 这将使查询不阻塞。 如果其它事务持有冲突的锁, 那么查询将引发 DatabaseError 异常. 您也可以使用select_for_update(skip_locked=True)忽略锁定的行。 nowaitskip_locked是互斥的,并尝试调用select_for_update()启用这两个选项将导致ValueError

目前,postgresqloraclemysql数据库后端支持select_for_update() 但是,MySQL不支持nowaitskip_locked参数。

使用不支持这些选项的数据库后端(如MySQL)将nowait=Trueskip_locked=True转换为select_for_update()将导致DatabaseError被提出。 这可以防止代码意外阻止。

在自动提交模式下使用select_for_update()评估支持的后台支持的查询 选择 ... 对于 UPDATE 是一个TransactionManagementError错误,因为在这种情况下行不锁定。 如果允许这个调用,那么可能造成数据损坏,而且这个功能很容易在事务外被调用。

在不支持的后端使用select_for_update() 选择 ... 对于 UPDATE 的后端 (例如SQLite) select_for_update() 将没有效果。 选择 ... 对于 UPDATE 将不会添加到查询中,并且如果在自动提交模式下使用了select_for_update(),则不会引发错误。

警告

Although select_for_update() normally fails in autocommit mode, since TestCase automatically wraps each test in a transaction, calling select_for_update() in a TestCase even outside an atomic() block will (perhaps unexpectedly) pass without raising a TransactionManagementError. 要正确测试select_for_update(),您应该使用TransactionTestCase

在Django更改1.11:

添加了skip_locked参数。

raw()

raw(raw_query, params=None, translations=None)

接收一个原始的SQL 查询,执行它并返回一个django.db.models.query.RawQuerySet 实例。 这个RawQuerySet 实例可以迭代以提供实例对象,就像普通的QuerySet 一样。

更多信息参见Performing raw SQL queries

警告

raw() 永远触发一个新的查询,而与之前的filter 无关。 因此,它通常应该从Manager 或一个全新的QuerySet 实例调用。

不返回QuerySet的方法

以下QuerySet方法评估QuerySet并返回而不是 一个 QuerySet

这些方法不使用高速缓存(请参阅Caching and QuerySets)。 这些方法每次被调用的时候都会查询数据库。

get()

get(**kwargs)

返回按照查询参数匹配到的对象,参数的格式应该符合 Field lookups的要求.

如果匹配到的对象个数不只一个的话,get() 将会触发MultipleObjectsReturned 异常. MultipleObjectsReturned 异常是模型类的属性.

如果根据给出的参数匹配不到对象的话,get() 将触发DoesNotExist 异常. 这个异常是模型类的属性. 例如:

Entry.objects.get(id='foo') # raises Entry.DoesNotExist

DoesNotExist异常从django.core.exceptions.ObjectDoesNotExist继承,因此您可以定位多个DoesNotExist异常。 例如:

from django.core.exceptions import ObjectDoesNotExist
try:
    e = Entry.objects.get(id=3)
    b = Blog.objects.get(id=1)
except ObjectDoesNotExist:
    print("Either the entry or blog doesn't exist.")

如果您希望一个查询器返回一行,则可以使用get()而不使用任何参数来返回该行的对象:

entry = Entry.objects.filter(...).exclude(...).get()

create()

create(**kwargs)

一个在一步操作中同时创建对象并且保存的便捷方法. 因此:

p = Person.objects.create(first_name="Bruce", last_name="Springsteen")

和:

p = Person(first_name="Bruce", last_name="Springsteen")
p.save(force_insert=True)

是等同的.

参数 force_insert 在其他的文档中有介绍, 它意味着一个新的对象一定会被创建. 正常情况中,你不必要担心这点. 然而, 如果你的model中有一个你手动设置主键, 并且这个值已经存在于数据库中, 调用 create()将会失败并且触发 IntegrityError 因为主键必须是唯一的. 如果你手动设置了主键,做好异常处理的准备.

get_or_create()

get_or_create(defaults=None, **kwargs)

一个通过给出的kwargs 来查询对象的便捷方法(如果你的模型中的所有字段都有默认值,可以为空),需要的话创建一个对象。

返回一个由(object, created)组成的元组,元组中的object 是一个查询到的或者是被创建的对象, created 是一个表示是否创建了新的对象的布尔值。

这主要用作样板代码的一种快捷方式。 像这样:

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()

如果模型的字段数量较大的话,这种模式就变的非常不易用了。 上面的示例可以用get_or_create()重写 :

obj, created = Person.objects.get_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'birthday': date(1940, 10, 9)},
)

任何传递给 get_or_create() 的关键字参数,除了一个可选的defaults,都将传递给get() 调用。 如果查找到一个对象,get_or_create() 返回一个包含匹配到的对象以及False 组成的元组。 如果查找到的对象超过一个以上,get_or_create 将引发MultipleObjectsReturned 如果查找不到对象get_or_create() 将会实例化并保存一个新的对象,返回一个由新的对象以及True 组成的元组。 新的对象将会大概按照以下的逻辑创建:

params = {k: v for k, v in kwargs.items() if '__' not in k}
params.update({k: v() if callable(v) else v for k, v in defaults.items()})
obj = self.model(**params)
obj.save()

它表示从非'defaults' 且不包含双下划线的关键字参数开始(暗示这是一个不精确的查询)。 然后将defaults 的内容添加进来,覆盖必要的键,并使用结果作为关键字参数传递给模型类。 如果defaults中有任何可调用值,请对它们进行评估。 这是对用到的算法的简单描述,但它包含了所有的相关的细节。 内部实现比这更多的错误检查,并处理一些额外的边缘条件;如果您有兴趣,请阅读代码。

如果你有一个名为'defaults__exact'的字段,并且想在get_or_create() 是用它作为精确查询,只需要使用defaults,像这样:

Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'})

当你使用手动指定的主键时,get_or_create() 方法与create()方法有相似的错误行为 。 如果需要创建一个对象而该对象的主键早已存在于数据库中,IntegrityError 异常将会被触发。

这个方法假设正确使用原子操作,正确的数据库配置和底层数据库的正确行为。 然而,如果数据库级别没有对get_or_create 中用到的kwargs 强制要求唯一性(参见uniqueunique_together),这个方法容易导致竞态条件可能会仍具有相同参数的多行同时插入。

如果你正在使用MySQL,请确保使用READ COMMITTED 隔离级别而不是默认的REPEATABLE READ,否则你将会遇到get_or_create 引发IntegrityError 但对象在接下来的get() 调用中并不存在的情况。

最后讲一句get_or_create() 在Django 视图中的使用。 请确保只在POST 请求中使用,除非你有充分的理由。 GET 请求不应该对数据有任何影响。 POST 则用于对数据产生影响的请求。 有关更多信息,请参阅HTTP规范中的 Safe methods

警告

你可以通过ManyToManyField 属性和反向关联使用get_or_create() 在这种情况下,你应该限制查询在关联的上下文内部。 如果你不一致地使用它,将可能导致完整性问题。

根据下面的模型:

class Chapter(models.Model):
    title = models.CharField(max_length=255, unique=True)

class Book(models.Model):
    title = models.CharField(max_length=256)
    chapters = models.ManyToManyField(Chapter)

你可以通过Book 的chapters 字段使用get_or_create(),但是它只会获取该Book 内部的上下文:

>>> book = Book.objects.create(title="Ulysses")
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, True)
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, False)
>>> Chapter.objects.create(title="Chapter 1")
<Chapter: Chapter 1>
>>> book.chapters.get_or_create(title="Chapter 1")
# Raises IntegrityError

发生这个错误时因为它尝试通过Book “Ulysses” 获取或者创建“Chapter 1”,但是它不能:关联关系不能获取这个chapter 因为它与这个book 不关联,但因为title 字段是唯一的它仍然不能创建。

在Django更改1.11:

defaults中增加了对可调用值的支持。

update_or_create()

update_or_create(defaults=None, **kwargs)

一个通过给出的kwargs 来更新对象的便捷方法, 如果需要的话创建一个新的对象。 defaults 是一个由 (field, value) 对组成的字典,用于更新对象。 defaults中的值可以是可调用的。

返回一个由 (object, created)组成的元组,元组中的object 是一个创建的或者是被更新的对象, created 是一个标示是否创建了新的对象的布尔值。

update_or_create 方法尝试通过给出的kwargs 去从数据库中获取匹配的对象。 如果找到匹配的对象,它将会依据defaults 字典给出的值更新字段。

这主要用作样板代码的一种快捷方式。 像这样:

defaults = {'first_name': 'Bob'}
try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
    for key, value in defaults.items():
        setattr(obj, key, value)
    obj.save()
except Person.DoesNotExist:
    new_values = {'first_name': 'John', 'last_name': 'Lennon'}
    new_values.update(defaults)
    obj = Person(**new_values)
    obj.save()

如果模型的字段数量较大的话,这种模式就变的非常不易用了。 上面的示例可以用 update_or_create() 重写:

obj, created = Person.objects.update_or_create(
    first_name='John', last_name='Lennon',
    defaults={'first_name': 'Bob'},
)

kwargs 中的名称如何解析的详细描述可以参见get_or_create()

和上文描述的get_or_create() 一样,这个方式容易导致竞态条件,如果数据库层级没有前置唯一性它会让多行同时插入。

在Django更改1.11:

defaults中增加了对可调用值的支持。

bulk_create()

bulk_create(objs, batch_size=None)

此方法以高效的方式(通常只有1个查询,无论有多少对象)将提供的对象列表插入到数据库中:

>>> Entry.objects.bulk_create([
...     Entry(headline='This is a test'),
...     Entry(headline='This is only a test'),
... ])

这有一些注意事项:

  • 将不会调用模型的save()方法,并且不会发送pre_savepost_save信号。
  • 它不适用于多表继承场景中的子模型。
  • 如果模型的主键是AutoField,则不会像save()那样检索并设置主键属性,除非数据库后端支持(当前只支持PostgreSQL)。
  • 它不适用于多对多关系。
在Django 1.10中的更改:

在使用PostgreSQL时,使用bulk_create()创建的对象支持设置主键。

batch_size参数控制在单个查询中创建的对象数。 默认值是在一个批处理中创建所有对象,除了SQLite,其中默认值为每个查询最多使用999个变量。

count()

count()

返回在数据库中对应的 QuerySet.对象的个数。 count() 永远不会引发异常。

例如:

# Returns the total number of entries in the database.
Entry.objects.count()

# Returns the number of entries whose headline contains 'Lennon'
Entry.objects.filter(headline__contains='Lennon').count()

len()在后台执行SELECT COUNT(*) len(),而不是将所有的记录加载到Python对象中并在结果上调用count()(除非你需要将对象加载到内存中, count()会更快)。

根据您使用的数据库(例如PostgreSQL vs. MySQL),count()可能返回一个长整型而不是普通的Python整数。 这是一个潜在的实现方案,不应该引起任何真实世界的问题。

请注意,如果您想要count()中的项目数量,并且还要从中检索模型实例(例如,通过迭代它),使用len(queryset)更有效,这不会像QuerySet一样导致额外的数据库查询。

in_bulk()

in_bulk(id_list=None)

获取主键值的列表,并返回将每个主键值映射到具有给定ID的对象的实例的字典。 如果未提供列表,则会返回查询集中的所有对象。

例如:

>>> Blog.objects.in_bulk([1])
{1: <Blog: Beatles Blog>}
>>> Blog.objects.in_bulk([1, 2])
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>}
>>> Blog.objects.in_bulk([])
{}
>>> Blog.objects.in_bulk()
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>, 3: <Blog: Django Weblog>}

如果你传递in_bulk()一个空列表,你会得到一个空的字典。

在Django更改1.10:

在旧版本中,id_list是必需的参数。

iterator()

iterator()

评估QuerySet(通过执行查询),并返回一个迭代器(参见 PEP 234)。 QuerySet通常在内部缓存其结果,以便在重复计算是不会导致额外的查询。 相反,iterator()将直接读取结果,而不在QuerySet级别执行任何缓存(内部,默认迭代器调用iterator()并高速缓存返回值)。 对于返回大量只需要访问一次的对象的QuerySet,这可以带来更好的性能和显着减少内存。

请注意,在已经求值了的iterator()上使用QuerySet会强制它再次计算,重复查询。

此外,使用iterator()会导致先前的prefetch_related()调用被忽略,因为这两个优化一起没有意义。

根据数据库后端,查询结果将一次性加载或使用服务器端游标从数据库流式传输。

使用服务器端光标

Oracle和PostgreSQL使用服务器端游标从数据库中流式传输结果,而不将整个结果集加载到内存中。

Oracle数据库驱动程序始终使用服务器端游标。

在PostgreSQL上,服务器端游标仅在DISABLE_SERVER_SIDE_CURSORS设置为False时使用。 如果您使用以事务池模式配置的连接池,请阅读Transaction pooling and server-side cursors 当服务器端游标被禁用时,该行为与不支持服务器端游标的数据库相同。

没有服务器端游标

MySQL和SQLite不支持流结果,因此Python数据库驱动程序将整个结果集加载到内存中。 然后,使用 PEP 249中定义的fetchmany()方法,使用数据库适配器将结果集转换为Python行对象。

在Django更改1.11:

添加PostgreSQL对服务器端游标的支持。

latest()

latest(field_name=None)

使用作为日期字段提供的field_name,按日期返回表中的最新对象。

此示例根据Entry字段返回表中的最新pub_date

Entry.objects.latest('pub_date')

如果模型的Meta指定get_latest_by,则可以将latest()参数留给earliest()或者field_name 默认情况下,Django将使用get_latest_by中指定的字段。

get()earliest()latest() raise DoesNotExist参数。

请注意,earliest()latest()仅仅是为了方便和可读性。

earliest()latest()可能会返回空日期的实例。

由于订购被委派给数据库,如果使用不同的数据库,则允许空值的字段的结果可能有所不同。 例如,PostgreSQL和MySQL排序空值,就好像它们高于非空值,而SQLite则相反。

您可能需要过滤掉空值:

Entry.objects.filter(pub_date__isnull=False).latest('pub_date')

earliest()

earliest(field_name=None)

除非方向更改,否则像latest()

first()

first()

返回结果集的第一个对象, 当没有找到时返回None. 如果 QuerySet 没有设置排序,则将会自动按主键进行排序

例如:

p = Article.objects.order_by('title', 'pub_date').first()

请注意,first()是一种简便方法,下面的代码示例等同于上面的示例:

try:
    p = Article.objects.order_by('title', 'pub_date')[0]
except IndexError:
    p = None

last()

last()

工作方式类似first(),只是返回的是查询集中最后一个对象。

aggregate()

aggregate(*args, **kwargs)

返回汇总值的字典(平均值,总和等) 通过QuerySet进行计算。 aggregate() 的每个参数指定返回的字典中将要包含的值。

Django 提供的聚合函数在下文的聚合函数文档中讲述。 因为聚合也是query expressions,你可以组合多个聚合以及值来创建复杂的聚合。

使用关键字参数指定的聚合将使用关键字参数的名称作为Annotation 的名称。 匿名的参数的名称将基于聚合函数的名称和模型字段生成。 复杂的聚合不可以使用匿名参数,它们必须指定一个关键字参数作为别名。

例如,当你使用Blog Entry 时,你可能想知道对Author 贡献的Blog Entry 的数目:

>>> from django.db.models import Count
>>> q = Blog.objects.aggregate(Count('entry'))
{'entry__count': 16}

通过使用关键字参数来指定聚合函数,你可以控制返回的聚合的值的名称:

>>> q = Blog.objects.aggregate(number_of_entries=Count('entry'))
{'number_of_entries': 16}

聚合的深入讨论,参见 the topic guide on Aggregation

exists()

exists()

如果QuerySet 包含任何结果,则返回True,否则返回False 它会试图用最简单和最快的方法完成查询,但它执行的方法与普通的QuerySet 查询QuerySet几乎相同。

exists() 用于搜寻对象是否在QuerySet 中以及QuerySet 是否存在任何对象,特别是QuerySet 比较大的时候。

查找具有唯一性字段(例如primary_key)的模型是否在一个QuerySet 中的最高效的方法是:

entry = Entry.objects.get(pk=123)
if some_queryset.filter(pk=entry.pk).exists():
    print("Entry contained in queryset")

它将比下面的方法快很多,这个方法要求对QuerySet 求值并迭代整个QuerySet:

if entry in some_queryset:
   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")

...但不是在很大程度上(因此需要一个大的查询来提高效率)。

另外,如果bool(some_queryset) 还没有求值,但你知道它将在某个时刻求值,那么使用some_queryset.exists() 将比简单地使用some_queryset 完成更多的工作(一个查询用于存在性检查,另外一个是后面的求值),后者将求值并检查是否有结果返回。

update()

update(**kwargs)

对指定的字段执行SQL更新查询,并返回匹配的行数(如果某些行已具有新值,则可能不等于已更新的行数)。

例如,要对2010年发布的所有博客条目启用评论,您可以执行以下操作:

>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)

(假设您的comments_on模型具有字段pub_dateEntry。)

您可以更新多个字段 - 没有多少字段的限制。 例如,在这里我们更新comments_onheadline字段:

>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False, headline='This is old')

update()方法立即应用,对更新的QuerySet的唯一限制是它只能更新模型主表中的列,而不是相关模型。 你不能这样做,例如:

>>> Entry.objects.update(blog__name='foo') # Won't work!

仍然可以根据相关字段进行过滤:

>>> Entry.objects.filter(blog__id=1).update(comments_on=True)

您不能在QuerySet上调用update(),该查询已截取一个切片,或者无法再进行过滤。

update()方法返回受影响的行数:

>>> Entry.objects.filter(id=64).update(comments_on=True)
1

>>> Entry.objects.filter(slug='nonexistent-slug').update(comments_on=True)
0

>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)
132

如果你只是更新一个记录,不需要对模型对象做任何事情,最有效的方法是调用update(),而不是将模型对象加载到内存中。 例如,而不是这样做:

e = Entry.objects.get(id=10)
e.comments_on = False
e.save()

…做这个:

Entry.objects.filter(id=10).update(comments_on=False)

使用update()还可以防止在加载对象和调用save()之间的短时间内数据库中某些内容可能发生更改的竞争条件。

Finally, realize that update() does an update at the SQL level and, thus, does not call any save() methods on your models, nor does it emit the pre_save or post_save signals (which are a consequence of calling Model.save()). 如果你想更新一个具有自定义save()方法的模型的记录,请循环遍历它们并调用save(),如下所示:

for e in Entry.objects.filter(pub_date__year=2010):
    e.comments_on = False
    e.save()

delete()

delete()

QuerySet中的所有行执行SQL删除查询,并返回删除的对象数和每个对象类型的删除次数的字典。

立即应用delete() 您不能在QuerySet上调用delete(),该查询已采取切片或以其他方式无法过滤。

例如,要删除特定博客中的所有条目:

>>> b = Blog.objects.get(pk=1)

# Delete all the entries belonging to this Blog.
>>> Entry.objects.filter(blog=b).delete()
(4, {'weblog.Entry': 2, 'weblog.Entry_authors': 2})

默认情况下,Django的ForeignKey模拟SQL约束ON DELETE CASCADE字,任何具有指向要删除的对象的外键的对象将与它们一起被删除。 像这样:

>>> blogs = Blog.objects.all()

# This will delete all Blogs and all of their Entry objects.
>>> blogs.delete()
(5, {'weblog.Blog': 1, 'weblog.Entry': 2, 'weblog.Entry_authors': 2})

这种级联的行为可以通过的ForeignKeyon_delete 参数自定义。

delete()方法执行批量删除,并且不会在模型上调用任何delete()方法。 但它会为所有已删除的对象(包括级联删除)发出pre_deletepost_delete信号。

Django需要获取对象到内存中以发送信号和处理级联。 然而,如果没有级联和没有信号,那么Django可以采取快速路径并删除对象而不提取到内存中。 对于大型删除,这可以显着减少内存使用。 执行的查询量也可以减少。

设置为on_delete DO_NOTHING的外键不会阻止删除快速路径。

请注意,在对象删除中生成的查询是实施详细信息,可能会更改。

as_manager()

classmethod as_manager()

类方法,返回Manager的实例与QuerySet的方法的副本。 有关详细信息,请参见使用QuerySet方法创建一个manager

Field查找

字段查询是指如何指定SQL WHERE 子句的内容。 它们通过QuerySetfilter(), exclude() and get()的关键字参数指定.

查阅简介, 请参考 模型和数据库查找文档.

Django的内置查找如下, 也可以为模型字段写入自定义查找

为了方便当没有提供查找类型时(例如Entry.objects.get(id=14)),查找类型默认为exact

exact

精确匹配。 如果为比较提供的值为NULL,它将被解释为SQL None(有关详细信息,请参阅isnull)。

例子:

Entry.objects.get(id__exact=14)
Entry.objects.get(id__exact=None)

SQL等价物:

SELECT ... WHERE id = 14;
SELECT ... WHERE id IS NULL;

MySQL比较

在MySQL中,可通过数据库表的“排序规则”设置来决定是否执行区分大小写的精确匹配。 这是一个数据库设置,而不是一个Django设置。 可以配置MySQL表以使用区分大小写的比较,但涉及一些折衷。 有关详细信息,请参阅数据库文档中的整理部分

iexact

不区分大小写的精确匹配 如果为比较提供的值为NULL,它将被解释为SQL None(有关详细信息,请参阅isnull)。

例如:

Blog.objects.get(name__iexact='beatles blog')
Blog.objects.get(name__iexact=None)

SQL等价物:

SELECT ... WHERE name ILIKE 'beatles blog';
SELECT ... WHERE name IS NULL;

请注意,第一个查询将匹配 'Beatles Blog', 'beatles blog', 'BeAtLes BLoG', etc.

SQLite用户

当使用SQLite后端和Unicode(非ASCII)字符串时,请记住关于字符串比较的database note SQLite不对Unicode字符串进行不区分大小写的匹配。

contains

大小写敏感的包含关系测试。

例如:

Entry.objects.get(headline__contains='Lennon')

SQL等效:

SELECT ... WHERE headline LIKE '%Lennon%';

请注意,这将匹配标题'Lennon honored today',但不符合'lennon honored today'.

SQLite用户

在SQLite中,使用LIKE子句进行查询时,Like子句并不会区分大小写; 对于SQLite,使用containsicontains得到的结果是相同的. 有关详细信息,请参阅database note

icontains

测试是否包含,不区分大小写。

例如:

Entry.objects.get(headline__icontains='Lennon')

等效于SQL:

SELECT ... WHERE headline ILIKE '%Lennon%';

SQLite用户

当使用SQLite后端和Unicode(非ASCII)字符串时,请记住关于字符串比较的database note

in

在给定的列表。

例如:

Entry.objects.filter(id__in=[1, 3, 4])

SQL等效:

SELECT ... WHERE id IN (1, 3, 4);

您还可以使用查询集动态评估值列表,而不是提供文字值列表:

inner_qs = Blog.objects.filter(name__contains='Cheddar')
entries = Entry.objects.filter(blog__in=inner_qs)

此查询集将作为subselect语句求值:

SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')

如果传递从values()values_list()得到的QuerySet作为__in查询的值,你需要确保只提取一个字段到结果中。 如下面代码所示,使用values只从查询结果中提取博客名称:

inner_qs = Blog.objects.filter(name__contains='Ch').values('name')
entries = Entry.objects.filter(blog__name__in=inner_qs)

下面这个例子将产生一个异常,由于内查询试图提取两个字段的值,但是查询语句只期望提取一个字段的值:

# Bad code! Will raise a TypeError.
inner_qs = Blog.objects.filter(name__contains='Ch').values('name', 'id')
entries = Entry.objects.filter(blog__name__in=inner_qs)

性能注意事项

对于使用嵌套查询和了解数据库服务器的性能特征(如果有疑问,去做基准测试)要谨慎。 一些数据库后端,最着名的是MySQL,不能很好地优化嵌套查询。 在这些情况下,提取值列表然后将其传递到第二个查询中更有效。 也就是说,执行两个查询,而不是一个:

values = Blog.objects.filter(
        name__contains='Cheddar').values_list('pk', flat=True)
entries = Entry.objects.filter(blog__in=list(values))

请注意list()调用Blog QuerySet以强制执行第一个查询。 没有它,将执行嵌套查询,因为QuerySets are lazy

gt

大于

例如:

Entry.objects.filter(id__gt=4)

SQL等效:

SELECT ... WHERE id > 4;

gte

大于或等于

lt

小于

lte

小于或等于

startswith

区分大小写,开始位置匹配

例如:

Entry.objects.filter(headline__startswith='Lennon')

SQL等效:

SELECT ... WHERE headline LIKE 'Lennon%';

SQLite doesn’t support case-sensitive LIKE statements; startswith acts like istartswith for SQLite.

istartswith

不区分大小写,开始位置匹配

例如:

Entry.objects.filter(headline__istartswith='Lennon')

SQL等效:

SELECT ... WHERE headline ILIKE 'Lennon%';

SQLite用户

当使用SQLite后端和Unicode(非ASCII)字符串时,请记住关于字符串比较的database note

endswith

区分大小写。

例如:

Entry.objects.filter(headline__endswith='Lennon')

SQL等效:

SELECT ... WHERE headline LIKE '%Lennon';

SQLite用户

SQLite doesn’t support case-sensitive LIKE statements; endswith acts like iendswith for SQLite. 有关更多信息,请参阅database note文档。

iendswith

不区分大小写。

例如:

Entry.objects.filter(headline__iendswith='Lennon')

SQL等效:

SELECT ... WHERE headline ILIKE '%Lennon'

SQLite用户

当使用SQLite后端和Unicode(非ASCII)字符串时,请记住关于字符串比较的database note

range

范围测试(包含于之中)。

例如:

import datetime
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))

SQL等效:

SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';

您可以在任何可以使用range的SQL中使用BETWEEN(对于日期,数字和偶数字符)。

警告

过滤具有日期的DateTimeField不会包含最后一天的项目,因为边界被解释为“给定日期的0am”。 如果pub_dateDateTimeField,上面的表达式将变成这个SQL:

SELECT ... WHERE pub_date BETWEEN '2005-01-01 00:00:00' and '2005-03-31 00:00:00';

一般来说,不能混合使用日期和数据时间。

date

对于datetime字段,将值作为日期转换。 允许链接附加字段查找。 获取日期值。

例如:

Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))

(此查找不包括等效的SQL代码片段,因为相关查询的实现因不同数据库引擎而异)。

USE_TZTrue时,字段将转换为当前时区,然后进行过滤。

year

对于日期和日期时间字段,确切的年匹配。 允许链接附加字段查找。 整数年。

例如:

Entry.objects.filter(pub_date__year=2005)
Entry.objects.filter(pub_date__year__gte=2005)

SQL等效:

SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31';
SELECT ... WHERE pub_date >= '2005-01-01';

(确切的SQL语法因每个数据库引擎而异)。

USE_TZTrue时,在过滤之前,datetime字段将转换为当前时区。

month

对于日期和日期时间字段,确切的月份匹配。 允许链接附加字段查找。 取整数1(1月)至12(12月)。

例如:

Entry.objects.filter(pub_date__month=12)
Entry.objects.filter(pub_date__month__gte=6)

SQL等效:

SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12';
SELECT ... WHERE EXTRACT('month' FROM pub_date) >= '6';

(确切的SQL语法因每个数据库引擎而异)。

USE_TZTrue时,在过滤之前,datetime字段将转换为当前时区。 这需要数据库中的time zone definitions in the database

day

对于日期和日期时间字段,具体到某一天的匹配。 允许链接附加字段查找。 取一个整数的天数。

例如:

Entry.objects.filter(pub_date__day=3)
Entry.objects.filter(pub_date__day__gte=3)

SQL等效:

SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';
SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3';

(确切的SQL语法因每个数据库引擎而异)。

请注意,这将匹配每月第三天(例如1月3日,7月3日等)的任何包含pub_date的记录。

USE_TZTrue时,在过滤之前,datetime字段将转换为当前时区。 这需要数据库中的time zone definitions in the database

week

Django中的新功能1.11。

对于日期和日期时间字段,请根据ISO-8601返回周号(1-52或53),即星期一开始的星期,星期四或之前的第一周。

例如:

Entry.objects.filter(pub_date__week=52)
Entry.objects.filter(pub_date__week__gte=32, pub_date__week__lte=38)

(此查找不包括等效的SQL代码片段,因为相关查询的实现因不同数据库引擎而异)。

USE_TZTrue时,字段将转换为当前时区,然后进行过滤。

week_day

对于日期和日期时间字段,“星期几”匹配。 允许链接附加字段查找。

取整数值,表示星期几从1(星期日)到7(星期六)。

例如:

Entry.objects.filter(pub_date__week_day=2)
Entry.objects.filter(pub_date__week_day__gte=2)

(此查找不包括等效的SQL代码片段,因为相关查询的实现因不同数据库引擎而异)。

请注意,这将匹配落在星期一(星期二)的任何记录(pub_date),而不管其出现的月份或年份。 周日被索引,第1天为星期天,第7天为星期六。

USE_TZTrue时,在过滤之前,datetime字段将转换为当前时区。 这需要数据库中的time zone definitions in the database

time

Django中的新功能1.11。

对于datetime字段,将值转换为时间。 允许链接附加字段查找。 获取datetime.time值。

例如:

Entry.objects.filter(pub_date__time=datetime.time(14, 30))
Entry.objects.filter(pub_date__time__between=(datetime.time(8), datetime.time(17)))

(此查找不包括等效的SQL代码片段,因为相关查询的实现因不同数据库引擎而异)。

USE_TZTrue时,字段将转换为当前时区,然后进行过滤。

hour

对于日期时间和时间字段,确切的时间匹配。 允许链接附加字段查找。 取0和23之间的整数。

例如:

Event.objects.filter(timestamp__hour=23)
Event.objects.filter(time__hour=5)
Event.objects.filter(timestamp__hour__gte=12)

SQL等效:

SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23';
SELECT ... WHERE EXTRACT('hour' FROM time) = '5';
SELECT ... WHERE EXTRACT('hour' FROM timestamp) >= '12';

(确切的SQL语法因每个数据库引擎而异)。

对于datetime字段,当USE_TZTrue时,值将过滤前转换为当前时区。

minute

对于日期时间和时间字段,确切的分钟匹配。 允许链接附加字段查找。 取0和59之间的整数。

例如:

Event.objects.filter(timestamp__minute=29)
Event.objects.filter(time__minute=46)
Event.objects.filter(timestamp__minute__gte=29)

SQL等效:

SELECT ... WHERE EXTRACT('minute' FROM timestamp) = '29';
SELECT ... WHERE EXTRACT('minute' FROM time) = '46';
SELECT ... WHERE EXTRACT('minute' FROM timestamp) >= '29';

(确切的SQL语法因每个数据库引擎而异)。

对于datetime字段,当USE_TZTrue时,值将被过滤前转换为当前时区。

second

对于日期时间和时间字段,确切的第二个匹配。 允许链接附加字段查找。 取0和59之间的整数。

例如:

Event.objects.filter(timestamp__second=31)
Event.objects.filter(time__second=2)
Event.objects.filter(timestamp__second__gte=31)

SQL等效:

SELECT ... WHERE EXTRACT('second' FROM timestamp) = '31';
SELECT ... WHERE EXTRACT('second' FROM time) = '2';
SELECT ... WHERE EXTRACT('second' FROM timestamp) >= '31';

(确切的SQL语法因每个数据库引擎而异)。

对于datetime字段,当USE_TZTrue时,值将过滤前转换为当前时区。

isnull

值为 FalseTrue, 相当于 SQL语句IS NULLIS NOT NULL.

例如:

Entry.objects.filter(pub_date__isnull=True)

SQL等效:

SELECT ... WHERE pub_date IS NULL;

regex

区分大小写的正则表达式匹配。

正则表达式语法是正在使用的数据库后端的语法。 在SQLite没有内置正则表达式支持的情况下,此功能由(Python)用户定义的REGEXP函数提供,因此正则表达式语法是Python的re模块。

例如:

Entry.objects.get(title__regex=r'^(An?|The) +')

SQL等价物:

SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL

SELECT ... WHERE REGEXP_LIKE(title, '^(An?|The) +', 'c'); -- Oracle

SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL

SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite

建议使用原始字符串(例如,r'foo'而不是'foo')来传递正则表达式语法。

iregex

不区分大小写的正则表达式匹配。

例如:

Entry.objects.get(title__iregex=r'^(an?|the) +')

SQL等价物:

SELECT ... WHERE title REGEXP '^(an?|the) +'; -- MySQL

SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'i'); -- Oracle

SELECT ... WHERE title ~* '^(an?|the) +'; -- PostgreSQL

SELECT ... WHERE title REGEXP '(?i)^(an?|the) +'; -- SQLite

聚合函数

Django 的django.db.models 模块提供以下聚合函数。 关于如何使用这些聚合函数的细节,参见the topic guide on aggregation 关于如何创建聚合函数,参数Aggregate 的文档。

警告

SQLite 不能直接处理日期/时间字段的聚合。 这是因为SQLite 中没有原生的日期/时间字段,Django 目前使用文本字段模拟它的功能。 在SQLite 中对日期/时间字段使用聚合将引发NotImplementedError

None 为空时,聚合函数函数将返回QuerySet 例如,如果0 中没有记录,None 聚合函数将返回Sum 而不是QuerySet QuerySet 是一个例外,如果0 为空,它将返回Count

所有聚合函数具有以下共同的参数:

expression

引用模型字段的一个字符串,或者一个query expression

output_field

用来表示返回值的model field,它是一个可选的参数。

在组合多个类型的字段时,只有在所有的字段都是相同类型的情况下,Django 才能确定output_field 否则,你必须自己提供output_field 参数。

**extra

这些关键字参数可以给聚合函数生成的SQL 提供额外的信息。

Avg

class Avg(expression, output_field=FloatField(), **extra)[source]

返回给定表达式的平均值,它必须是数值,除非您指定不同的output_field

  • 默认的别名:<field>__avg
  • 返回类型:float(或指定任何output_field的类型)

Count

class Count(expression, distinct=False, **extra)[source]

返回与expression 相关的对象的个数。

  • 默认的别名:<field>__count
  • 返回类型:int

有一个可选的参数:

distinct

如果distinct=True,Count 将只计算唯一的实例。 它等同于COUNT(DISTINCT <field>) SQL 语句。 默认值为False

Max

class Max(expression, output_field=None, **extra)[source]

返回expression 的最大值。

  • 默认的别名:<field>__max
  • 返回类型:与输入字段的类型相同,如果提供则为 output_field 类型

Min

class Min(expression, output_field=None, **extra)[source]

返回expression 的最小值。

  • 默认的别名:<field>__min
  • 返回类型:与输入字段的类型相同,如果提供则为 output_field 类型

StdDev

class StdDev(expression, sample=False, **extra)[source]

返回expression 的标准差。

  • 默认的别名:<field>__stddev
  • 返回类型:float

有一个可选的参数:

sample

默认情况下,StdDev 返回群体的标准差。 但是,如果sample=True,返回的值将是样本的标准差。

SQLite

SQLite 没有直接提供StdDev 有一个可用的实现是SQLite 的一个扩展模块。 参见SQlite 的文档 中获取并安装这个扩展的指南。

Sum

class Sum(expression, output_field=None, **extra)[source]

计算expression 的所有值的和。

  • 默认的别名:<field>__sum
  • 返回类型:与输入字段的类型相同,如果提供则为 output_field 类型

Variance

class Variance(expression, sample=False, **extra)[source]

返回expression 的方差。

  • 默认的别名:<field>__variance
  • 返回类型:float

有一个可选的参数:

sample

默认情况下,Variance 返回群体的方差。 但是,如果sample=True,返回的值将是样本的方差。

SQLite

SQLite 没有直接提供Variance 有一个可用的实现是SQLite 的一个扩展模块。 参见SQlite 的文档 中获取并安装这个扩展的指南。