QuerySet API参考

本文档描述了QuerySet API的细节。 它建立在modeldatabase query指南中的内容上,所以在阅读这些指南之前,您可能需要阅读和理解这些文档。

在整个这个参考文献中,我们将使用database query guide中介绍的example Weblog models

QuerySet s被评估时

在内部,一个QuerySet可以被构造,过滤,切片,并且通常在没有实际击中数据库的情况下传递。 实际上没有数据库活动发生,直到你做一些事情来评估查询集。

您可以通过以下方式评估QuerySet

  • 迭代。 一个QuerySet是可迭代的,并且在您第一次迭代它时执行它的数据库查询。 例如,这将打印数据库中所有条目的标题:

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

    注意:如果所有你想要做的是确定是否至少存在一个结果,那么不要使用它。 使用exists()会更有效率。

  • Slicing. 正如Limiting QuerySets中所解释的,可以使用Python的数组切片语法对QuerySet进行切片。 Slicing an unevaluated QuerySet usually returns another unevaluated QuerySet, but Django will execute the database query if you use the “step” parameter of slice syntax, and will return a list. 切片已经评估过的QuerySet也会返回一个列表。

    还要注意的是,即使对未评估的QuerySet进行切片也会返回另一个未评估的QuerySet,因此不允许进一步修改它(例如,添加更多的过滤器或修改排序)很好地转换成SQL,它也不会有明确的含义。

  • Pickling/Caching. See the following section for details of what is involved when pickling QuerySets. 对于本节来说,重要的是从数据库中读取结果。

  • repr(). 当您调用repr()时,会计算QuerySet 这是为了方便Python交互式解释器,所以当交互使用API​​时,您可以立即看到您的结果。

  • len(). 当您调用len()时,将对QuerySet进行评估。 正如您所期望的那样,这将返回结果列表的长度。

    注意:如果您只需要确定集合中的记录数(并且不需要实际的对象),那么使用SQL的SELECT t1 > COUNT(*) 正因如此,Django提供了一个count()方法。

  • list(). 通过调用list()强制对QuerySet进行评估。 例如:

    entry_list = list(Entry.objects.all())
    
  • bool(). Testing a QuerySet in a boolean context, such as using bool(), or, and or an if statement, will cause the query to be executed. 如果至少有一个结果,则QuerySetTrue,否则为False 例如:

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

    注意:如果您只想确定是否存在至少一个结果(并且不需要实际对象),那么使用exists()会更有效。

Pickling QuerySets

If you pickle a QuerySet, this will force all the results to be loaded into memory prior to pickling. 酸洗通常被用作缓存的先驱,当缓存的查询集被重新加载时,你希望结果已经存在并准备好使用(从数据库中读取可能需要一些时间,从而破坏缓存的目的)。 这意味着当你拔掉一个QuerySet时,它包含了pick pick的结果,而不是当前在数据库中的结果。

如果您只想腌制必要的信息以便稍后从数据库中重新创建QuerySet,请腌制QuerySetquery属性。 然后你可以使用如下代码重新创建原始的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的一部分。 但是,按照此处所述,腌制和取消属性的​​内容是安全的(并且完全支持)。

版本之间不能共享泡菜

QuerySets的酱菜只对用于生成它们的Django版本有效。 如果使用Django版本N生成一个pickle,则不能保证pickle在Django版本N + 1中是可读的。 不应将腌菜作为长期档案战略的一部分。

由于pickle兼容性错误很难诊断,比如默默的破坏了对象,所以当你试图在不同于被pickle的Django版本中取消一个queryset时,会引发一个RuntimeWarning

QuerySet API

以下是QuerySet的正式声明:

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

通常当你与一个QuerySet进行交互时,你可以通过chaining filters来使用它。 To make this work, most QuerySet methods return new querysets. 本节稍后会详细介绍这些方法。

QuerySet类有两个可用于内省的公共属性:

有序 T0> ¶ T1>

True if the QuerySet is ordered — i.e. has an order_by() clause or a default ordering on the model. False否则。

分贝 T0> ¶ T1>

如果现在执行此查询,将使用的数据库。

注意

存在QuerySet参数的query参数,以便专门的查询子类可以重建内部查询状态。 参数的值是该查询状态的不透明表示,不是公共API的一部分。 简单地说:如果你需要问,你不需要使用它。

返回新的QuerySet s 的方法

Django提供了一系列的QuerySet细化方法,可以修改QuerySet返回的结果类型或SQL查询的执行方式。

filter()

filter(**kwargs)

返回包含匹配给定查找参数的对象的新的QuerySet

查找参数(**kwargs)应该采用下面字段查找中描述的格式。 多个参数通过AND连接到底层的SQL语句中。

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

exclude()

排除 T0>( ** kwargs T1>)¶ T2>

返回包含not匹配给定查找参数的对象的新QuerySet

查找参数(**kwargs)应该采用下面字段查找中描述的格式。 在底层SQL语句中,多个参数通过AND连接在一起,整个事物被封装在NOT()中。

这个例子排除了pub_date晚于2005-1-3 AND 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或其标题为“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)

使用提供的query expressions的列表来注释QuerySet中的每个对象。 表达式可以是简单的值,对模型(或任何相关模型)上的字段的引用,或者已经在与对象中的对象相关的对象上计算的聚集表达式(平均值,和等) QuerySet

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

Django提供的聚合函数在下面的聚合函数中描述。

使用关键字参数指定的注释将使用关键字作为注释的别名。 匿名参数将根据聚合函数的名称和正在聚合的模型字段为其生成别名。 仅引用单个字段的聚合表达式可以是匿名参数。 其他一切都必须是关键字参数。

例如,如果您正在操作博客列表,则可能需要确定每个博客中有多少个条目:

>>> 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属性,但是通过使用关键字参数来指定聚合函数,您可以控制注释的名称:

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

有关聚合的深入讨论,请参阅the topic guide on Aggregation

order_by()

ORDER_BY T0>( *字段 T1>)¶ T2>

默认情况下,由QuerySet返回的结果由模型的Metaordering选项给出的排序元组排序。 您可以通过使用order_by方法在per- QuerySet基础上覆盖它。

例:

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

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

Entry.objects.order_by('?')

Note: order_by('?') queries may be expensive and slow, depending on the database backend you’re using.

要按不同模型中的字段排序,请使用与跨模型关系进行查询时相同的语法。 也就是说,该字段的名称后跟一个双下划线(__),接着是新模型中字段的名称,以此类推,以便连接多个模型。 例如:

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

如果您尝试按与另一个模型的关系的字段进行排序,那么Django将在相关模型上使用默认排序,如果没有指定Meta.ordering,则按相关模型的主键排序。 例如,由于Blog模型没有指定默认排序:

Entry.objects.order_by('blog')

...与以下内容相同:

Entry.objects.order_by('blog__id')

如果Blog排序 = ,那么第一个查询集将与以下内容相同:

Entry.objects.order_by('blog__name')

您也可以通过调用表达式中的asc()desc()来按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')

Here, there could potentially be multiple ordering data for each Event; each Event with multiple children will be returned multiple times into the new QuerySet that order_by() creates. 换句话说,在QuerySet上使用order_by()可能会返回比您开始处理更多的项目 - 这可能既不是预期的也不是有用的。

因此,在使用多值字段来排序结果时要小心。 If you can be sure that there will only be one ordering piece of data for each of the items you’re ordering, this approach should not present problems. 如果没有,确保结果是你所期望的。

没有办法指定排序是否区分大小写。 在区分大小写方面,Django会对结果进行排序,但是您的数据库后端通常会对它们进行排序。

您可以通过将Lower转换为小写字母的字段进行排序,这将实现大小写一致的排序:

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

如果您不希望将任何顺序应用于查询,甚至不需要默认排序,则可以不带参数调用order_by()

您可以通过检查QuerySet.ordered属性来判断查询是否被排序,如果已经排序了QuerySet,属性将会是True任何方式。

每个order_by()调用都将清除以前的任何顺序。 例如,该查询将按pub_date排序,而不是headline

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

警告

订购不是免费的。 您添加到订单的每个字段都会导致数据库成本。 您添加的每个外键都会隐式地包含其所有默认排序。

如果查询没有指定的顺序,那么结果将从数据库以未指定的顺序返回。 一个特定的顺序只有在通过唯一标识结果中每个对象的一组字段进行排序时才能得到保证。 例如,如果一个name字段不是唯一的,按顺序排列并不能保证具有相同名称的对象总是以相同的顺序出现。

reverse()

reverse()

使用reverse()方法来颠倒查询集元素返回的顺序。 第二次调用reverse()将恢复到正常方向。

要检索查询集中的“最后”五个项目,您可以这样做:

my_queryset.reverse()[:5]

请注意,这与从Python中的序列末尾进行切片不太一样。 上面的例子将返回最后一个项目,然后倒数第二个项目等等。 If we had a Python sequence and looked at seq[-5:], we would see the fifth-last item first. Django不支持这种访问模式(从最后切片),因为在SQL中无法高效地进行访问。

Also, note that reverse() should generally only be called on a QuerySet which has a defined ordering (e.g., when querying against a model which defines a default ordering, or when using order_by()). 如果给定的QuerySet没有定义这样的顺序,调用reverse()就没有实际效果(调用reverse()

distinct()

不同 T0>( *字段 T1>)¶ T2>

返回在其SQL查询中使用SELECT DISTINCT的新的QuerySet 这消除了查询结果中的重复行。

默认情况下,一个QuerySet不会消除重复的行。 在实践中,这很少是一个问题,因为像Blog.objects.all()这样的简单查询不会引入重复结果行的可能性。 但是,如果查询跨越多个表,那么在计算QuerySet时可能会得到重复的结果。 那就是当你使用distinct()的时候。

注意

order_by()调用中使用的任何字段都包含在SQL SELECT列中。 当与distinct()结合使用时,有时会导致意外的结果。 如果您通过相关模型的字段进行排序,则这些字段将被添加到选定的列中,并且可能会使重复的行显得不同。 由于额外的列不会出现在返回的结果中(它们只是为了支持排序),它有时看起来像是返回不同的结果。

同样,如果使用values()查询来限制所选的列,则任何order_by()(或默认模型排序)中使用的列仍将涉及并可能影响结果的唯一性。

这里的道德是,如果你正在使用distinct(),请注意相关模型的排序。 类似地,当使用distinct()values()时,在按values()调用进行排序时要小心。

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

注意

When you specify field names, you must provide an order_by() in the QuerySet, and the fields in order_by() must start with the fields in distinct(), in the same order.

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

...将不起作用,因为查询将按blog__name排序,从而与DISTINCT ON表达式不匹配。 You’d have to explicitly order by the relation _id field (blog_id in this case) or the referenced one (blog__pk) to make sure both expressions match.

values()

*字段**表达式

当用作迭代器时,返回一个返回字典的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.'}]>

values()方法使用可选的位置参数*fields,它们指定SELECT应限制的字段名称。 如果指定了字段,则每个字典将仅包含指定字段的字段键/值。 如果不指定字段,则每个字典将包含数据库表中每个字段的键和值。

例:

>>> 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()方法也可以传递给annotate()的可选关键字参数**expressions

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

值得一提的一些微妙之处:

  • If you have a field called foo that is a ForeignKey, the default values() call will return a dictionary key called foo_id, since this is the name of the hidden model attribute that stores the actual value (the foo attribute refers to the related model). 在调用values()并传入字段名称时,可以传入foofoo_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()distinct()一起使用时,请注意排序会影响结果。 有关详细信息,请参阅distinct()中的注释。

  • If you use a values() clause after an extra() call, any fields defined by a select argument in the extra() must be explicitly included in the values() call. values()调用之后进行的任何extra()调用将会忽略其额外的选定字段。

  • Calling only() and defer() after values() doesn’t make sense, so doing so will raise a NotImplementedError.

当您知道只需要少量可用字段中的值时,这非常有用,而且您不需要模型实例对象的功能。 只选择需要使用的字段会更有效率。

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

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

制作Django的人宁愿首先放置所有影响SQL的方法,然后(可选)使用任何影响输出的方法(如values()),但这并不重要。 这是你真正炫耀你的个人主义的机会。

您还可以通过OneToOneFieldForeignKeyManyToManyField属性在相关模型中引用具有反向关系的字段:

>>> 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*flat = Falsenamed = 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是错误的。

你可以通过named=True得到结果作为namedtuple()

>>> Entry.objects.values_list('id', 'headline', named=True)
<QuerySet [Row(id=1, headline='First entry'), ...]>

使用一个命名的元组可能会使结果更具可读性,代价是将结果转换成命名元组的代价很小。

如果您没有将值传递给values_list(),它将按照声明的顺序返回模型中的所有字段。

常见的需求是获取特定模型实例的特定字段值。 为了达到这个目的,可以使用values_list(),后跟一个get()调用:

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

values() and values_list() are both intended as optimizations for a specific use case: retrieving a subset of data without the overhead of creating a model instance. 当处理多对多和其他多值关系(比如反向外键的一对多关系)时,这个比喻就会分崩离析,因为“一行一个对象”假设不成立。

例如,请注意跨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中表达式的支持。

在Django 2.0中更改:

The named parameter was added.

dates()

日期字段kindorder ='ASC'

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

field应该是模型的DateField的名称。 kind should be either "year", "month" or "day". 结果列表中的每个datetime.date对象将被截断为给定的type

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

order,默认为'ASC',应该是'ASC''DESC' 这指定了如何排序结果。

例子:

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

datetimesfield_namekindorder ='ASC'tzinfo = None¶ T5>

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

field_name应该是模型的DateTimeField的名称。

kind should be either "year", "month", "day", "hour", "minute" or "second". 结果列表中的每个datetime.datetime对象被截断为给定的type

order,默认为'ASC',应该是'ASC''DESC' 这指定了如何排序结果。

tzinfo defines the time zone to which datetimes are converted prior to truncation. 事实上,根据使用的时区,给定的日期时间具有不同的表示。 这个参数必须是一个datetime.tzinfo对象。 如果None,Django使用current time zone USE_TZFalse时,它不起作用。

注意

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

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

none()

无 T0>()¶ T1>

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

例子:

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

all()

所有 T0>()¶ T1>

返回当前QuerySet(或QuerySet子类)的副本 这在您可能想要传入模型管理器或QuerySet并对结果进行进一步过滤的情况下非常有用。 在任何一个对象上调用all()之后,肯定会有一个QuerySet来处理。

When a QuerySet is evaluated, it typically caches its results. If the data in the database might have changed since a QuerySet was evaluated, you can get updated results for the same query by calling all() on a previously evaluated QuerySet.

union()

union* other_qsall = False
Django 1.11新增功能

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

>>> qs1.union(qs2, qs3)

The UNION operator selects only distinct values by default. 要允许重复值,请使用all=True参数。

union(), intersection(), and difference() return model instances of the type of the first QuerySet even if the arguments are QuerySets of other models. 只要SELECT列表在所有QuerySet中是相同的(至少是类型,相同的顺序)。 In such cases, you must use the column names from the first QuerySet in QuerySet methods applied to the resulting QuerySet. 例如:

>>> qs1 = Author.objects.values_list('name')
>>> qs2 = Entry.objects.values_list('headline')
>>> qs1.union(qs2).order_by('name')

In addition, only LIMIT, OFFSET, COUNT(*), ORDER BY, and specifying columns (i.e. slicing, count(), order_by(), and values()/values_list()) are allowed on the resulting QuerySet. 此外,数据库对组合查询中允许的操作进行限制。 例如,大多数数据库不允许在组合查询中使用LIMITOFFSET

在Django 1.11.4中更改:

COUNT(*) support was added.

intersection()

相交 T0>( * other_qs T1>)¶ T2>
Django 1.11新增功能

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

>>> qs1.intersection(qs2, qs3)

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

difference()

差 T0>( * other_qs T1>)¶ T2>
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)

Sometimes, the Django query syntax by itself can’t easily express a complex WHERE clause. For these edge cases, Django provides the extra() QuerySet modifier — a hook for injecting specific clauses into the SQL generated by a QuerySet.

使用此方法作为最后的手段

这是一个旧的API,我们打算在将来某个时候弃用。 只有在不能使用其他查询集方法表示查询时才使用它。 如果您确实需要使用它,请使用QuerySet.extra关键字文件与您的用例(请先查看现有票证的列表)增强QuerySet API以允许删除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字符串中引用占位符。 由于%s周围的引号,此示例易受SQL注入攻击:

"select col from sometable where othercol = '%s'"  # unsafe!

您可以阅读更多关于Django的SQL injection protection的工作原理。

根据定义,这些额外的查找可能不能移植到不同的数据库引擎(因为你明确地写了SQL代码)并且违反了DRY原则,所以如果可能的话,你应该避免它们。

指定一个或多个paramsselectwheretables 没有一个参数是必需的,但是你至少应该使用其中的一个。

  • 选择

    使用select参数可以将额外的字段放在SELECT子句中。 它应该是一个字典映射属性名称到SQL子句用来计算该属性。

    例:

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

    因此,每个Entry对象将具有一个额外的属性is_recent,一个表示条目的pub_date是否大于1月1日的布尔值, 2006年。

    Django将给定的SQL代码片段直接插入到SELECT语句中,所以上面例子的结果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'
        },
    )
    

    在这种特殊情况下,我们利用查询在FROM子句中已经包含blog_blog表的事实。

    上面例子的结果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属性是一个字典,所以需要注意,以便参数与额外的选择部分正确匹配。 在这种情况下,您应该为select值使用collections.OrderedDict,而不仅仅是一个普通的Python字典。

    这将工作,例如:

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

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

  • where / tables

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

    where and tables both take a list of strings. 所有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()调用放在queryset结构的前面,这样你的表就是该表的第一个用途。 最后,如果一切都失败了,查看产生的查询并重写你的where除了使用给你的额外表的别名。 每次以相同的方式构造查询集时,别名都是相同的,所以可以依赖别名来不改变。

  • ORDER_BY

    如果您需要使用通过extra()包含的一些新字段或表来对生成的查询集进行排序,请使用order_by参数来指定extra() 这些字符串应该是模型字段(如查询集中的正常order_by()方法),table_name.column_name形式或者您指定的列的别名select参数到extra()

    例如:

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

    这将把is_recent为true的所有项目排序在结果集的前面(TrueFalse之前按降序排序)。

    这表明顺便说一下,您可以对extra()进行多次调用,并且其行为与您期望的相同(每次添加新约束)。

  • PARAMS

    The where parameter described above may use standard Python database string placeholders — '%s' to indicate parameters the database engine should automatically quote. params参数是要替换的任何额外参数的列表。

    例:

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

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

    坏:

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

    好:

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

警告

如果您正在MySQL上执行查询,请注意,在混合类型时,MySQL的静默类型强制可能会导致意外的结果。 如果您查询字符串类型列,但是使用整数值,则在执行比较之前,MySQL将强制表中所有值的类型为整数。 For example, if your table contains the values 'abc', 'def' and you query for WHERE mycolumn=0, both rows will match. 为了防止这种情况,请在查询中使用该值之前执行正确的类型转换。

defer()

延迟 T0>( *字段 T1>)¶ T2>

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

这是通过传递字段的名称来不加载到defer()

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

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

你可以多次调用defer() 每次调用都会将新字段添加到延期集中:

# Defers both the body and headline fields.
Entry.objects.defer("body").filter(rating=5).defer("headline")

字段添加到延期集合的顺序无关紧要。 使用已经被延期的字段名称调用defer()是无害的(字段将被延迟)。

您可以通过使用标准的双下划线表示法来推迟相关模型中的字段加载(如果相关模型是通过select_related()加载的)来分隔相关字段:

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

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

# Load all fields immediately.
my_queryset.defer(None)

即使您要求,模型中的某些字段也不会被延期。 永远不能推迟加载主键。 如果您正在使用select_related()来检索相关模型,则不应将从主模型连接到相关模型的字段加载延迟,否则会导致错误。

注意

下面的defer()方法(和它的表弟,only())仅用于高级用例。 They provide an optimization for when you have analyzed your queries closely and understand exactly what information you need and have measured that the difference between returning the fields you need and the full set of fields for the model will be significant.

Even if you think you are in the advanced use-case situation, only use defer() when you cannot, at queryset load time, determine if you will need the extra fields or not. 如果您经常加载和使用特定的数据子集,那么您可以做出的最佳选择是规范化模型,并将未加载的数据放入单独的模型(和数据库表)中。 If the columns must stay in the one table for some reason, create a model with Meta.managed = False (see the managed attribute documentation) containing just the fields you normally need to load and use that where you might otherwise call 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()

仅 T0>( *字段 T1>)¶ T2>

only()方法或多或少与defer()相反。 您可以在检索模型时使用应该not的字段进行调用。 如果你有一个几乎所有的字段都需要延期的模型,那么使用only()来指定补充的字段集合可以使代码更简单。

假设你有一个名为nameagebiography的模型。 以下两个查询集在延迟字段方面是相同的:

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

使用 T0>(别名 T1>)¶ T2>

如果您使用多个数据库,则此方法用于控制将针对哪个数据库评估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, of=())

返回将锁定行直到事务结束的查询集,生成一个 选择 ... 对于 UPDATE 支持的数据库上的SQL语句。

例如:

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

所有匹配的条目将被锁定,直到交易块结束,这意味着其他交易将被阻止改变或获取它们的锁定。

通常,如果另一个事务已经获得了所选行之一的锁,则查询将被阻塞,直到锁被释放。 如果这不是您想要的行为,请调用select_for_update(nowait=True) 这将使呼叫非阻塞。 If a conflicting lock is already acquired by another transaction, DatabaseError will be raised when the queryset is evaluated. 您也可以使用select_for_update(skip_locked=True)来忽略锁定的行。 nowaitskip_locked是互斥的,并尝试在启用这两个选项的情况下调用select_for_update()将导致ValueError

By default, select_for_update() locks all rows that are selected by the query. 例如,除了查询集模型的行之外,select_related()中指定的相关对象的行被锁定。 If this isn’t desired, specify the related objects you want to lock in select_for_update(of=(...)) using the same fields syntax as select_related(). 使用值'self'来引用查询集的模型。

您不能在可空关系上使用select_for_update()

>>> Person.objects.select_related('hometown').select_for_update()
Traceback (most recent call last):
...
django.db.utils.NotSupportedError: FOR UPDATE cannot be applied to the nullable side of an outer join

为了避免这种限制,如果你不关心它们,你可以排除空对象:

>>> Person.objects.select_related('hometown').select_for_update().exclude(hometown=None)
<QuerySet [<Person: ...)>, ...]>

Currently, the postgresql, oracle, and mysql database backends support select_for_update(). 但是,MySQL不支持nowaitskip_lockedof

Passing nowait=True, skip_locked=True, or of to select_for_update() using database backends that do not support these options, such as MySQL, raises a NotSupportedError. 这可以防止代码意外阻塞。

使用select_for_update()在自动提交模式下在后端支持查询集 选择 ... 对于 UPDATE is a TransactionManagementError error because the rows are not locked in that case. 如果允许,这将有助于数据损坏,并且可能很容易由调用预期在一个事务之外运行的代码引起。

在不支持的后端使用select_for_update() 选择 ... 对于 UPDATE (如SQLite)将不起作用。 选择 ... 对于 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. To properly test select_for_update() you should use TransactionTestCase.

某些表达式可能不被支持

PostgreSQL不支持带有Window表达式的select_for_update()

在Django 1.11中更改:

添加了skip_locked参数。

在Django 2.0中更改:

添加了参数的of

raw()

rawraw_queryparams = Nonetranslations = None

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

有关更多信息,请参阅Performing raw SQL queries

警告

raw() always triggers a new query and doesn’t account for previous filtering. 因此,通常应该从Manager或从新的QuerySet实例中调用它。

不返回QuerySet s 的方法

The following QuerySet methods evaluate the QuerySet and return something other than a QuerySet.

这些方法不使用缓存(请参阅Caching and QuerySets)。 相反,他们每次调用数据库时都会查询数据库。

get()

获得 T0>( ** kwargs T1>)¶ T2>

返回与给定的查找参数匹配的对象,应该采用Field lookups中描述的格式。

get() raises MultipleObjectsReturned if more than one object was found. MultipleObjectsReturned异常是模型类的一个属性。

get() raises a DoesNotExist exception if an object wasn’t found for the given parameters. 这个异常是模型类的一个属性。 例:

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

创建 T0>( ** kwargs T1>)¶ T2>

创建对象并将其保存在一个步骤中的便捷方法。 从而:

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参数在其他地方有记录,但意味着总会创建一个新的对象。 通常你不需要担心这个。 但是,如果您的模型包含您设置的手动主键值,并且该值已经存在于数据库中,那么调用create()将会失败,并返回IntegrityError主键必须是唯一的。 如果您正在使用手动主键,请准备好处理异常。

get_or_create()

get_or_createdefaults = None** kwargs

使用给定的kwargs查找对象的简便方法(如果您的模型具有所有字段的缺省值,则可能为空),如果需要,则创建一个。

返回(object, 创建的)的元组,其中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)},
)

Any keyword arguments passed to get_or_create()except an optional one called defaults — will be used in a get() call. If an object is found, get_or_create() returns a tuple of that object and False. If multiple objects are found, get_or_create raises 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的字段,并且想在get_or_create()中使用它作为一个精确的查找,那么就使用'defaults__exact'

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

当您使用手动指定的主键时,get_or_create()方法与create()具有类似的错误行为。 如果需要创建对象并且数据库中已存在密钥,则会引发IntegrityError

此方法是原子假设正确的使用,正确的数据库配置和正确的基础数据库的行为。 但是,如果在数据库级别对get_or_create调用中使用的kwargs没有执行唯一性(请参阅uniqueunique_together

If you are using MySQL, be sure to use the READ COMMITTED isolation level rather than REPEATABLE READ (the default), otherwise you may see cases where get_or_create will raise an IntegrityError but the object won’t appear in a subsequent get() call.

最后,在Django视图中使用get_or_create() 请确保仅在POST请求中使用它,除非您有充分的理由不要。 GET requests shouldn’t have any effect on data. 每当对页面的请求对数据产生副作用时,请使用POST 有关更多信息,请参阅HTTP规范中的 Safe methods

警告

您可以使用get_or_create()ManyToManyField属性和反向关系。 在这种情况下,您将限制查询在该关系的上下文中。 如果你不一致地使用它,那么你可能会遇到一些完整性问题。

作为以下型号:

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的章节字段来使用get_or_create(),但它只会在该书的上下文中进行提取:

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

这是因为它试图通过“尤利西斯”得到或者创造出“第一章”,但是它不能做任何一件事情:关系不能取那章,因为它和那本书没有关系,它不能创建它,因为title字段应该是唯一的。

在Django 1.11中更改:

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

update_or_create()

update_or_createdefaults = None** kwargs

用给定的kwargs更新对象的一种简便方法,如有必要,创建一个新对象。 defaults是用于更新对象的(字段,值)对的字典。 defaults中的值可以是可调用的。

返回(object, 创建的)的元组,其中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_createobjsbatch_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)。

  • 它不适用于多对多的关系。

  • 它将objs转换为一个列表,如果它是一个生成器,它将完全评估objs 转换允许检查所有对象,以便可以首先插入具有手动设置的主键的任何对象。 如果您想要批量插入对象而不一次评估整个生成器,只要对象没有任何手动设置的主键,就可以使用这种技术:

    from itertools import islice
    
    batch_size = 100
    objs = (Entry(headling'Test %s' % i) for i in range(1000))
    while True:
        batch = list(islice(objs, batch_size))
        if not batch:
            break
        Entry.objects.bulk_create(batch, batch_size)
    

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

count()

计数 T0>()¶ T1>

返回一个整数,表示与QuerySet匹配的数据库中的对象数。 The count() method never raises exceptions.

例:

# 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()

A count() call performs a SELECT COUNT(*) behind the scenes, so you should always use count() rather than loading all of the record into Python objects and calling len() on the result (unless you need to load the objects into memory anyway, in which case len() will be faster).

请注意,如果您需要QuerySet中的项目数,并且还从中检索模型实例(例如,通过遍历它),则使用len(queryset)这将不会像count()那样引起额外的数据库查询。

in_bulk()

in_bulkid_list = Nonefield_name ='pk'

获取这些值的字段值(id_list)和field_name的列表,并返回一个字典,将每个值映射到具有给定字段值的对象实例。 如果未提供id_list,则返回查询集中的所有对象。 field_name必须是唯一的字段,并且默认为主键。

例:

>>> 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>}
>>> Blog.objects.in_bulk(['beatles_blog'], field_name='slug')
{'beatles_blog': <Blog: Beatles Blog>}

If you pass in_bulk() an empty list, you’ll get an empty dictionary.

在Django 2.0中更改:

添加了field_name参数。

iterator()

迭代 T0>( CHUNK_SIZE = 2000 T1>)¶ T2>

通过执行查询来评估QuerySet,并在结果上返回一个迭代器(参见 PEP 234)。 一个QuerySet通常在内部缓存其结果,以便重复的评估不会导致额外的查询。 相比之下,iterator()将直接读取结果,而不会在QuerySet级别进行任何缓存(内部默认迭代器调用iterator()并缓存返回值)。 For a QuerySet which returns a large number of objects that you only need to access once, this can result in better performance and a significant reduction in memory.

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

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

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

使用服务器端游标

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

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

对于服务器端游标,chunk_size参数指定要在数据库驱动程序级别缓存的结果数量。 获取更大的块会减少数据库驱动程序和数据库之间的往返次数,但会以内存为代价。

在PostgreSQL上,只有当DISABLE_SERVER_SIDE_CURSORS设置为False时才会使用服务器端游标。 Read Transaction pooling and server-side cursors if you’re using a connection pooler configured in transaction pooling mode. 当禁用服务器端游标时,其行为与不支持服务器端游标的数据库相同。

没有服务器端游标

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

chunk_size参数控制Django从数据库驱动程序中检索的批量大小。 较大的批量减少了与数据库驱动程序通信的开销,代价是内存消耗略有增加。

chunk_size,2000的默认值来自在psycopg邮件列表上的计算

假定行数为10-20列,混合使用文本和数字数据,2000将获取少于100KB的数据,如果循环提前退出,这似乎是传输的行数和丢弃的数据之间的良好折衷。
在Django 1.11中更改:

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

在Django 2.0中更改:

添加了chunk_size参数。

latest()

最新 T0>( *字段 T1>)¶ T2>

根据给定的字段返回表中的最新对象。

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

Entry.objects.latest('pub_date')

您也可以根据几个字段选择最新的。 例如,当两个条目具有相同的pub_date时,要选择具有最早的expire_dateEntry

Entry.objects.latest('pub_date', '-expire_date')

'-expire_date'中的负号表示按降序顺序对expire_date进行排序。 由于latest()得到最后的结果,因此选择具有最早的expire_dateEntry

如果模型的Meta指定了get_latest_by,则可以省略earliest()latest()的任何参数。 get_latest_by中指定的字段将被默认使用。

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

请注意,earliest()latest()纯粹是为了方便和可读性而存在的。

在Django 2.0中更改:

增加了对几个参数的支持。

earliest() and latest() may return instances with null dates.

由于排序委托给数据库,如果您使用不同的数据库,则允许空值的字段上的结果可能会按不同的顺序排列。 例如,PostgreSQL和MySQL对空值进行排序,就好像它们高于非空值,而SQLite则相反。

您可能需要过滤掉空值:

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

earliest()

最早 T0>( *字段 T1>)¶ T2>

除非方向改变,否则工作方式与latest()类似。

first()

第一 T0>()¶ T1>

返回查询集匹配的第一个对象,如果没有匹配的对象,则返回None 如果QuerySet没有定义顺序,那么查询集由主键自动排序。 这可能会影响聚合结果,如Interaction with default ordering or order_by()的交互中所述。

例:

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

最后 T0>()¶ T1>

first()一样工作,但返回查询集中的最后一个对象。

aggregate()

集合* args** kwargs

返回通过QuerySet计算的聚合值(平均值,总和等)的字典。 aggregate()的每个参数指定一个将包含在返回的字典中的值。

Django提供的聚合函数在下面的聚合函数中描述。 Since aggregates are also query expressions, you may combine aggregates with other aggregates or values to create complex aggregates.

使用关键字参数指定的聚合将使用关键字作为注释的名称。 匿名参数将根据聚合函数的名称和正在聚合的模型字段为其生成一个名称。 复杂聚合不能使用匿名参数,而必须指定一个关键字参数作为别名。

例如,当您处理博客条目时,您可能想知道贡献了博客条目的作者数量:

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

存在 T0>()¶ T1>

如果QuerySet包含任何结果,则返回True,否则返回False This tries to perform the query in the simplest and fastest way possible, but it does execute nearly the same query as a normal QuerySet query.

exists() is useful for searches relating to both object membership in a QuerySet and to the existence of any objects in a QuerySet, particularly in the context of a large QuerySet.

查找具有唯一字段的模型(如primary_key)是否是QuerySet的成员的最有效方法是:

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

这将比以下更快,这需要评估和遍历整个查询集:

if entry in some_queryset:
   print("Entry contained in 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")

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

另外,如果一个some_queryset还没有被评估,但是你知道它会在某一时刻,那么使用some_queryset.exists()将会做更多的全面工作查询存在检查加一个额外的检索结果)比简单地使用bool(some_queryset),检索结果,然后检查是否有任何返回。

update()

更新 T0>( ** kwargs T1>)¶ T2>

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

例如,要为2010年发布的所有博客条目打开评论,可以这样做:

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

(假定你的Entry模型有字段pub_datecomments_on。)

您可以更新多个字段 - 有多少个没有限制。 例如,我们在这里更新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()). If you want to update a bunch of records for a model that has a custom save() method, loop over them and call save(), like this:

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

delete()

删除 T0>()¶ T1>

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

By default, Django’s ForeignKey emulates the SQL constraint ON DELETE CASCADE — in other words, any objects with foreign keys pointing at the objects to be deleted will be deleted along with them. 例如:

>>> 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的ForeignKeys不妨碍删除快速路径。

请注意,在删除对象中生成的查询是一个可能会更改的实现细节。

as_manager()

类方法 as_manager T0>()¶ T1>

Class方法,该方法返回Manager的实例和QuerySet方法的副本。 有关更多详细信息,请参阅Creating a manager with QuerySet methods

Field查找

字段查找是如何指定SQL WHERE子句的内容。 它们被指定为QuerySet方法filter()exclude()get()

有关介绍,请参阅models and database queries documentation

下面列出了Django的内置查找。 也可以为模型字段编写custom lookups

为了方便起见,不提供查找类型(如在Entry.objects.get(id=14)中),查找类型被假定为exact

exact

完全符合。 如果提供的比较值是None,它将被解释为一个SQL NULL(更多细节参见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中,数据库表的“整理”设置决定了exact比较是否区分大小写。 这是一个数据库设置,不是 Django设置。 可以将MySQL表配置为使用区分大小写的比较,但涉及一些权衡。 有关详细信息,请参阅databases文档中的collation section

iexact

不区分大小写的精确匹配。 如果提供的比较值是None,它将被解释为一个SQL NULL(更多细节参见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 / t5>'BeAtLes BLoG'

SQLite用户

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

contains

区分大小写的容器测试。

例:

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

等价的SQL:

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

Note this will match the headline 'Lennon honored today' but not 'lennon honored today'.

SQLite用户

SQLite不支持区分大小写的LIKE语句;对于SQLite,contains就像icontains一样。 有关更多信息,请参阅database note

icontains

不区分大小写的遏制测试。

例:

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

等价的SQL:

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

SQLite用户

在使用SQLite后端和非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)

这个查询集将被评估为子选择语句:

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

如果您将values()values_list()中的QuerySet作为值传递给__in ,你需要确保你只提取结果中的一个字段。 例如,这将工作(过滤博客名称):

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

注意围绕Blog QuerySet调用list()来强制执行第一个查询。 没有它,嵌套查询将被执行,因为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不支持区分大小写的LIKE语句;对于SQLite,startswith就像istartswith一样。

istartswith

不区分大小写开始。

例:

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

等价的SQL:

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

SQLite用户

在使用SQLite后端和非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后端和非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';

您可以在任何可以在SQL中使用BETWEEN的地方使用range来获取日期,数字和偶数字符。

警告

使用日期过滤DateTimeField将不包括最后一天的项目,因为界限被解释为“给定日期的凌晨0点”。 如果pub_dateDateTimeField,则上述表达式将转换为此SQL:

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

一般来说,你不能混合日期和日期。

date

对于日期时间字段,将值转换为日期。 允许链接额外的字段查找。 记录一个日期值。

例:

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时,日期时间字段将在过滤之前转换为当前时区。

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时,日期时间字段将在过滤之前转换为当前时区。 这需要数据库中的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语法因每个数据库引擎而异。)

请注意,这将在月份的第三天匹配任何带有pub_date的记录,例如1月3日,7月3日等。

USE_TZTrue时,日期时间字段将在过滤之前转换为当前时区。 这需要数据库中的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代码片段。)

请注意,无论发生的月份或年份如何,这个记录都会与周一(第2天的第2天)的pub_date匹配。 星期几以第一天为周日,第七天为星期六。

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

quarter

Django 2.0新增功能

对于日期和日期时间字段,“四分之一”匹配。 允许链接额外的字段查找。 取1到4之间的整数值表示一年的季度。

在第二季度(4月1日至6月30日)检索条目的示例:

Entry.objects.filter(pub_date__quarter=2)

(由于相关查询的实现在不同的数据库引擎中有所不同,因此此查找不包含等效的SQL代码片段。)

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

time

Django 1.11新增功能

对于日期时间字段,将值转换为时间。 允许链接额外的字段查找。 需要一个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语法因每个数据库引擎而异。)

对于日期时间字段,当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语法因每个数据库引擎而异。)

对于日期时间字段,当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语法因每个数据库引擎而异。)

对于日期时间字段,当USE_TZTrue时,在过滤之前将值转换为当前时区。

isnull

取对应于IS NULL的SQL查询的TrueFalse 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

注意

与空的QuerySet一起使用时,聚合函数返回None 例如,如果QuerySet不包含任何条目,则Sum聚合函数将返回None而不是0 An exception is Count, which does return 0 if the QuerySet is empty.

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

expression

引用模型中字段的字符串或query expression

output_field

表示返回值的model field的可选参数

注意

在组合多个字段类型时,如果所有字段的类型相同,那么Django只能确定output_field 否则,你必须自己提供output_field

filter

Django 2.0新增功能

用于过滤聚合行的可选Q object

有关示例,请参阅Conditional aggregationFiltering on annotations

**extra

关键字参数可以为聚合生成的SQL提供额外的上下文。

Avg

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

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

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

Count

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

返回通过提供的表达式相关的对象的数量。

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

有一个可选的参数:

不同 T0> ¶ T1>

如果distinct=True,则计数将只包含唯一的实例。 This is the SQL equivalent of COUNT(DISTINCT <field>). 默认值是False

Max

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

返回给定表达式的最大值。

  • 默认别名:<field>__max
  • 返回类型:与输入字段相同,或者output_field(如果提供)

Min

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

返回给定表达式的最小值。

  • 默认别名:<field>__min
  • 返回类型:与输入字段相同,或者output_field(如果提供)

StdDev

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

返回提供的表达式中数据的标准偏差。

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

有一个可选的参数:

样品 T0> ¶ T1>

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

SQLite的

SQLite不提供StdDev开箱即用。 一个实现可用作SQLite的扩展模块。 有关获取和安装此扩展的说明,请参阅SQlite文档

Sum

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

计算给定表达式的所有值的总和。

  • 默认别名:<field>__sum
  • 返回类型:与输入字段相同,或者output_field(如果提供)

Variance

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

返回提供的表达式中数据的方差。

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

有一个可选的参数:

样品 T0> ¶ T1>

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

SQLite的

SQLite不提供Variance开箱即用。 一个实现可用作SQLite的扩展模块。 有关获取和安装此扩展的说明,请参阅SQlite文档