本文档描述查询集 API 的细节。它创建在模型和数据库查询指南的基础上,因此在阅读本文档以前,你也许须要首先阅读这两部分的文档。python
本文档将通篇使用在数据库查询指南中用到的Weblog 模型的例子。mysql
在内部,能够建立、过滤、切片和传递查询集而不用真实操做数据库。在你对查询集作求值以前,不会发生任何实际的数据库操做。正则表达式
你可使用下列方法对查询集求值:算法
迭代。查询集是可迭代的,它在首次迭代查询集时执行实际的数据库查询。例如, 下面的语句会将数据库中全部Entry 的headline 打印出来:sql
for e in Entry.objects.all(): print(e.headline)
注意:不要使用上面的语句来验证在数据库中是否至少存在一条记录。使用 exists()方法更高效。数据库
切片。 正如在限制查询集中解释的那样, 可使用Python 的序列切片语法对一个查询集进行分片。一个未求值的查询集进行切片一般返回另外一个未求值的查询集,可是若是你使用切片的”step“参数,Django 将执行数据库查询并返回一个列表。对一个已经求值的查询集进行切片将返回一个列表。express
还要注意,虽然对未求值的查询集进行切片返回另外一个未求值的查询集,可是却不能够进一步修改它了(例如,添加更多的Filter,或者修改排序的方式),由于这将不太好翻译成SQL并且含义也不清晰。django
序列化/缓存。 序列化查询集的细节参见下面一节。本节提到它的目的是强调序列化将读取数据库。后端
repr()。 当对查询集调用repr() 时,将对它求值。这是为了在Python 交互式解释器中使用的方便,这样你能够在交互式使用这个API 时当即看到结果。缓存
len()。 当你对查询集调用len() 时, 将对它求值。正如你指望的那样,返回一个查询结果集的长度。
注:若是你只须要知道集合中记录的个数(并不须要真实的对象),使用数据库层级的SELECT COUNT(*) 计数将更加高效。为此,Django 提供了 一个count() 方法.
list()。 对查询集调用list() 将强制对它求值。例如:
entry_list = list(Entry.objects.all())
bool()。 测试一个查询集的布尔值,例如使用bool()、or、and 或者if 语句将致使查询集的执行。若是至少有一个记录,则查询集为True,不然为False。例如:
if Entry.objects.filter(headline="Test"): print("There is at least one Entry with the headline Test")
注:若是你须要知道是否存在至少一条记录(而不须要真实的对象),使用 exists() 将更加高效。
若是你Pickle一个查询集,它将在Pickle 以前强制将全部的结果加载到内存中。Pickle 一般用于缓存以前,而且当缓存的查询集从新加载时,你但愿结果已经存在随时准备使用(从数据库读取耗费时间,就失去了缓存的目的)。这意味着当你Unpickle查询集时,它包含Pickle 时的结果,而不是当前数据库中的结果。
若是此后你只想Pickle 必要的信息来从数据库从新建立查询集,能够Pickle查询集的query 属性。而后你可使用相似下面的代码从新建立原始的查询集(不用加载任何结果):
>>> 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 的结果
查询集的Pickle 只能用于生成它们的Django 版本中。若是你使用Django 的版本N 生成一个Pickle,不保证这个Pickle 在Django 的版本N+1 中能够读取。Pickle 不可用于归档的长期策略。
New in Django 1.8.
由于Pickle 兼容性的错误很难诊断例如产生损坏的对象,当你试图Unpickle 的查询集与Pickle 时的Django 版本不一样,将引起一个RuntimeWarning。
下面是对于查询集的正式定义:
class QuerySet([model=None, query=None, using=None])[source]
一般你在使用QuerySet时会以链式的filter 来使用。为了让这个能工做,大部分QuerySet 方法返回新的QuerySet。这些方法在本节将详细讲述。
QuerySet 类具备两个公有属性用于内省:
ordered[source]
若是QuerySet 是排好序的则为True —— 例若有一个order_by() 子句或者模型有默认的排序。不然为False .
db[source]
若是如今执行,则返回将使用的数据库。
注
QuerySet 存在query 参数是为了让具备特殊查询用途的子类如GeoQuerySet 能够从新构造内部的查询状态。这个参数的值是查询状态的不透明的表示,不是一个公开的API。简而言之:若是你有疑问,那么你实际上不须要使用它。
Django 提供了一系列 的QuerySet筛选方法,用于改变 QuerySet 返回的结果类型或者SQL查询执行的方式。
filter(**kwargs)
返回一个新的QuerySet,包含与给定的查询参数匹配的对象。
查找的参数(**kwargs)应该知足下文字段查找中的格式。在底层的SQL 语句中,多个参数经过AND 链接。
若是你须要执行更复杂的查询(例如,使用OR 语句查询),你可使用Q 对象。
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 对象。
annotate(*args, **kwargs)
使用提供的查询表达式Annotate 查询集中的每一个对象。查询表达式能够是一个简单的值、模型(或关联模型)字段的一个引用或对查询集中的对象一个聚合函数(平均值、和等)。
New in Django 1.8:
以前版本的Django 值容许聚合函数用做Annotation。如今可使用各类表达式annotate 一个模型。
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(*fields)
默认状况下,QuerySet 根据模型Meta 类的ordering 选项排序。你可使用order_by 方法给每一个QuerySet 指定特定的排序。
例如:
Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')
上面的结果将按照pub_date 降序排序,而后再按照headline 升序排序。"-pub_date" 前面的负号表示降序排序。隐式的是升序排序。若要随机排序,请使用"?",像这样:
Entry.objects.order_by('?')
注: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')
经过关联字段排序QuerySet 还可以不用带来JOIN 产生的花费,方法是引用关联字段的_id:
# No Join Entry.objects.order_by('blog_id') # Join Entry.objects.order_by('blog__id')
New in Django 1.7:
QuerySet 经过关联字段进行排序不用带来JOIN 产生的开销。
你还能够经过调用表达式的asc() 或者desc(),根据查询表达式排序:
Entry.objects.order_by(Coalesce('summary', 'headline').desc())
New in Django 1.8:
增长根据查询表达式排序。
若是你还用到distinct(),在根据关联模型中的字段排序时要当心。distinct() 中有一个备注讲述关联模型的排序如何对结果产生影响。
注
指定一个多值字段来排序结果(例如,一个ManyToManyField 字段或者ForeignKey 字段的反向关联)。
考虑下面的状况:
class Event(Model): parent = models.ForeignKey('self', related_name='children') date = models.DateField() Event.objects.order_by('children__date')
这里,每一个Event 可能有多个潜在的排序数据;换句话说, 用 order_by()方法对 QuerySet对象进行操做会返回一个扩大版的新QuerySet对象——新增的条目也许并无什么卵用,你也用不着它们。
所以,当你使用多值字段对结果进行排序时要格外当心。
没有方法指定排序是否考虑大小写。对于大小写的敏感性,Django 将根据数据库中的排序方式排序结果。
你能够经过Lower将一个字段转换为小写来排序,它将达到大小写一致的排序:
Entry.objects.order_by(Lower('headline').desc())
New in Django 1.8:
新增根据表达式如Lower 来排序。
若是你不想对查询作任何排序,即便是默认的排序,能够不带参数调用order_by()。
你能够经过检查QuerySet.ordered 属性来知道查询是不是排序的,若是QuerySet 有任何方式的排序它将为True。
每一个order_by() 都将清除前面的任何排序。例如,下面的查询将按照pub_date 排序,而不是headline:
Entry.objects.order_by('headline').order_by('pub_date')
警告
排序不是没有开销的操做。添加到排序中的每一个字段都将带来数据库的开销。添加的每一个外键也都将隐式包含进它的默认排序。
reverse()
reverse() 方法反向排序QuerySet 中返回的元素。第二次调用reverse() 将恢复到原有的排序。
如要获取QuerySet 中最后五个元素,你能够这样作:
my_queryset.reverse()[:5]
注意,这与Python 中从一个序列的末尾进行切片有点不同。上面的例子将首先返回最后一个元素,而后是倒数第二个元素,以此类推。若是咱们有一个Python 序列,当咱们查看seq[-5:] 时,咱们将一会儿获得倒数五个元素。Django 不支持这种访问模型(从末尾进行切片),由于它不可能利用SQL 高效地实现。
同时还要注意,reverse() 应该只在一个已经定义排序的QuerySet 上调用(例如,在一个定义了默认排序的模型上,或者使用order_by() 的时候)。若是QuerySet 没有定义排序,调用reverse() 将不会有任何效果(在调用reverse() 以前没有定义排序,那么调用以后仍保持没有定义)。
distinct([*fields])
返回一个在SQL 查询中使用SELECT DISTINCT 的新QuerySet。它将去除查询结果中重复的行。
默认状况下,QuerySet 不会去除重复的行。在实际应用中,这通常不是个问题,由于像Blog.objects.all() 这样的简单查询不会引入重复的行。可是,若是查询跨越多张表,当对QuerySet 求值时就可能获得重复的结果。这时候你应该使用distinct()。
注
order_by() 调用中的任何字段都将包含在SQL 的 SELECT 列中。与distinct() 一块儿使用时可能致使预计不到的结果。若是你根据关联模型的字段排序,这些fields将添加到查询的字段中,它们可能产生本应该是惟一的重复的行。由于多余的列没有出如今返回的结果中(它们只是为了支持排序),有时候看上去像是返回了不明确的结果。
示例(除第一个示例外,其余示例都只能在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') [...]
values(*fields)
返回一个ValuesQuerySet —— QuerySet 的一个子类,迭代时返回字典而不是模型实例对象。
每一个字典表示一个对象,键对应于模型对象的属性名称。
下面的例子将values() 与普通的模型对象进行比较:
# This list contains a Blog object. >>> Blog.objects.filter(name__startswith='Beatles') [<Blog: Beatles Blog>] # This list contains a dictionary. >>> Blog.objects.filter(name__startswith='Beatles').values() [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]
values() 接收可选的位置参数*fields,它指定SELECT 应该限制哪些字段。若是指定字段,每一个字典将只包含指定的字段的键/值。若是没有指定字段,每一个字典将包含数据库表中全部字段的键和值。
例如:
>>> Blog.objects.values() [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}], >>> Blog.objects.values('id', 'name') [{'id': 1, 'name': 'Beatles Blog'}]
值得注意的几点:
若是你有一个字段foo 是一个ForeignKey,默认的values() 调用返回的字典将有一个叫作foo_id 的键,由于这是保存实际的值的那个隐藏的模型属性的名称(foo 属性引用关联的模型)。当你调用values() 并传递字段的名称,传递foo 或foo_id 均可以,获得的结果是相同的(字典的键会与你传递的字段名匹配)。
例如:
>>> Entry.objects.values() [{'blog_id': 1, 'headline': 'First Entry', ...}, ...] >>> Entry.objects.values('blog') [{'blog': 1}, ...] >>> Entry.objects.values('blog_id') [{'blog_id': 1}, ...]
当values() 与distinct() 一块儿使用时,注意排序可能影响最终的结果。详细信息参见distinct() 中的备注。
若是values() 子句位于extra() 调用以后,extra() 中的select 参数定义的字段必须显式包含在values() 调用中。values() 调用后面的extra() 调用将忽略选择的额外的字段。
在values() 以后调用only() 和defer() 不太合理,因此将引起一个NotImplementedError。
New in Django 1.7:
新增最后一点。之前,在values() 以后调用only() 和defer() 是容许的,可是它要么会崩溃要么返回错误的结果。
ValuesQuerySet 用于你知道你只须要字段的一小部分,而不须要用到模型实例对象的函数。只选择用到的字段固然更高效。
最后,要注意ValuesQuerySet 是QuerySet 的子类,它实现了大部分相同的方法。你能够对它调用filter()、order_by() 等等。这表示下面的两个调用彻底相同:
Blog.objects.values().order_by('id') Blog.objects.order_by('id').values()
Django 的做者喜欢将影响SQL 的方法放在前面,而后放置影响输出的方法(例如values()),可是实际上无所谓。这是卖弄你个性的好机会。
你能够经过OneToOneField、ForeignKey 和 ManyToManyField 属性反向引用关联的模型的字段:
Blog.objects.values('name', 'entry__headline') [{'name': 'My blog', 'entry__headline': 'An entry'}, {'name': 'My blog', 'entry__headline': 'Another entry'}, ...]
警告
由于ManyToManyField 字段和反向关联可能有多个关联的行,包含它们可能致使结果集的倍数放大。若是你在values() 查询中包含多个这样的字段将更加明显,这种状况下将返回全部可能的组合。
values_list(*fields, flat=False)
与values() 相似,只是在迭代时返回的是元组而不是字典。每一个元组包含传递给values_list() 调用的字段的值 —— 因此第一个元素为第一个字段,以此类推。例如:
>>> Entry.objects.values_list('id', 'headline') [(1, 'First entry'), ...]
若是只传递一个字段,你还能够传递flat 参数。若是为True,它表示返回的结果为单个值而不是元组。一个例子会让它们的区别更加清晰:
>>> Entry.objects.values_list('id').order_by('id') [(1,), (2,), (3,), ...] >>> Entry.objects.values_list('id', flat=True).order_by('id') [1, 2, 3, ...]
若是有多个字段,传递flat 将发生错误。
若是你不传递任何值给values_list(),它将返回模型中的全部字段,以它们在模型中定义的顺序。
注意,这个方法返回ValuesListQuerySet。这个类的行为相似列表。大部分时候它足够用了,可是若是你须要一个真实的Python 列表对象,能够对它调用list(),这将会对查询集求值。
dates(field, kind, order='ASC')
返回一个 DateQuerySet ,就是提取 QuerySet 查询中所包含的日期,将其组成一个新的 datetime.datetime 对象的列表。
field 是你的 model 中的 DateField 或 DateTimeField 字段名称。
kind 是 "year", "month" 或 "day" 之一。 每一个 datetime.datetime 对象都会根据所给的 type 进行截减。
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(field_name, kind, order='ASC', tzinfo=None)
返回一个QuerySet 就是提取 QuerySet 查询中所包含的时间,相似dates。
none() 返回一个 EmptyQuerySet -- 它是一个运行时只返回空列表的 QuerySet。它常常用在这种场合:你要返回一个空列表,可是调用者却须要接收一个 QuerySet 对象。(这时,就能够用它代替空列表)
Examples:
>>> Entry.objects.none() [] >>> from django.db.models.query import EmptyQuerySet >>> isinstance(Entry.objects.none(), EmptyQuerySet) True
all()
返回当前QuerySet(或QuerySet 子类) 的副本。它能够用于在你但愿传递一个模型管理器或QuerySet 并对结果作进一步过滤的状况。无论对哪种对象调用all(),你都将得到一个能够工做的QuerySet。
当对QuerySet进行求值时,它一般会缓存其结果。若是数据库中的数据在QuerySet求值以后可能已经改变,你能够经过在之前求值过的QuerySet上调用相同的all() 查询以得到更新后的结果。
select_related(*fields)
返回一个QuerySet,当执行它的查询时它沿着外键关系查询关联的对象的数据。它会生成一个复杂的查询并引发性能的损耗,可是在之后使用外键关系时将不须要数据库查询。
下面的例子解释了普通查询和select_related() 查询的区别。下面是一个标准的查询:
# Hits the database. e = Entry.objects.get(id=5) # Hits the database again to get the related Blog object. b = e.blog
下面是一个select_related 查询:
# Hits the database. e = Entry.objects.select_related('blog').get(id=5) # Doesn't hit the database, because e.blog has been prepopulated # in the previous query. b = e.blog
select_related() 可用于任何对象的查询集:
from django.utils import timezone # Find all the blogs with entries scheduled to be published in the future. blogs = set() for e in Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog'): # Without select_related(), this would make a database query for each # loop iteration in order to fetch the related blog for each entry. blogs.add(e.blog)
filter() 和select_related() 链的顺序不重要。下面的查询集是等同的:
Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog') Entry.objects.select_related('blog').filter(pub_date__gt=timezone.now())
你能够沿着外键查询。若是你有如下模型:
from django.db import models class City(models.Model): # ... pass class Person(models.Model): # ... hometown = models.ForeignKey(City) class Book(models.Model): # ... author = models.ForeignKey(Person)
... 那么Book.objects.select_related('author__hometown').get(id=4) 调用将缓存关联的Person 和关联的 City:
b = Book.objects.select_related('author__hometown').get(id=4) p = b.author # Doesn't hit the database. c = p.hometown # Doesn't hit the database. b = Book.objects.get(id=4) # No select_related() in this example. p = b.author # Hits the database. c = p.hometown # Hits the database.
在传递给select_related() 的字段中,你可使用任何ForeignKey 和OneToOneField。
在传递给select_related 的字段中,你还能够反向引用OneToOneField —— 也就是说,你能够回溯到定义OneToOneField 的字段。此时,可使用关联对象字段的related_name,而不要指定字段的名称。
有些状况下,你但愿对不少对象调用select_related(),或者你不知道全部的关联关系。在这些状况下,能够调用不带参数的select_related()。它将查找能找到的全部不可为空外键 —— 能够为空的外键必须明确指定。大部分状况下不建议这样作,由于它会使得底层的查询很是复杂而且返回的不少数据都不是真实须要的。
若是你须要清除QuerySet 上之前的select_related 添加的关联字段,能够传递一个None 做为参数:
>>> without_relations = queryset.select_related(None)
链式调用select_related 的工做方式与其它方法相似 —— 也就是说,select_related('foo', 'bar') 等同于select_related('foo').select_related('bar')。
Changed in Django 1.7:
在之前,后者等同于select_related('bar')。
对于多对多字段(ManyToManyField)和一对多字段,可使用prefetch_related()来进行优化。或许你会说,没有一个叫OneToManyField的东西啊。实际上 ,ForeignKey就是一个多对一的字段,而被ForeignKey关联的字段就是一对多字段了。
做用和方法
prefetch_related()和select_related()的设计目的很类似,都是为了减小SQL查询的数量,可是实现的方式不同。后者是经过JOIN语句,在SQL查询内解决问题。可是对于多对多关系,使用SQL语句解决就显得有些不太明智,由于JOIN获得的表将会很长,会致使SQL语句运行时间的增长和内存占用的增长。如有n个对象,每一个对象的多对多字段对应Mi条,就会生成Σ(n)Mi 行的结果表。
prefetch_related()的解决方法是,分别查询每一个表,而后用Python处理他们之间的关系。
例如:
from django.db import models class Topping(models.Model): name = models.CharField(max_length=30) class Pizza(models.Model): name = models.CharField(max_length=50) toppings = models.ManyToManyField(Topping) def __str__(self): # __unicode__ on Python 2 return "%s (%s)" % (self.name, ", ".join(topping.name for topping in self.toppings.all())) and run: >>> Pizza.objects.all() ["Hawaiian (ham, pineapple)", "Seafood (prawns, smoked salmon)"...
extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
有些状况下,Django的查询语法难以简单的表达复杂的 WHERE 子句,对于这种状况, Django 提供了 extra() QuerySet 修改机制 — 它能在 QuerySet生成的SQL从句中注入新子句
Warning
不管什么时候你都须要很是当心的使用extra().
因为产品差别的缘由,这些自定义的查询难以保障在不一样的数据库之间兼容(由于你手写 SQL 代码的缘由),并且违背了 DRY 原则,因此如非必要,仍是尽可能避免写 extra。
extra能够指定一个或多个 参数,例如 select, where or tables. 这些参数都不是必须的,可是你至少要使用一个select。The select 参数可让你在 SELECT 从句中添加其余字段信息,它应该是一个字典,存放着属性名到 SQL 从句的映射。
Example:
Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
结果集中每一个 Entry 对象都有一个额外的属性is_recent, 它是一个布尔值,表示 Entry对象的pub_date 是否晚于 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从句中却无须这样。
例如:
Blog.objects.extra( select=OrderedDict([('a', '%s'), ('b', '%s')]), select_params=('one', 'two'))
defer(*fields)
在某些数据复杂的环境下,你的 model 可能包含很是多的字段,可能某些字段包含很是多的数据(好比,文档字段),或者将其转化为 Python 对象会消耗很是多的资源。在这种状况下,有时你可能并不须要这种字段的信息,那么你可让 Django 不读取它们的数据。
将不想载入的字段的名称传给 defer() 方法,就能够作到延后载入:
Entry.objects.defer("lede", "body")
延后截入字段的查询返回的还是 model 类的实例。在你访问延后载入字段时,你仍能够得到字段的内容,所不一样的是,内容是在你访问延后字段时才读取数据库的,而普通字段是在运行查询(queryset)时就一次性从数据库中读取数据的。
你能够屡次调用 defer() 方法。每一个调用均可以添加新的延后载入字段:
# Defers both the body and lede fields. Entry.objects.defer("body").filter(headline="Lennon").defer("lede")
对延后载入字段进行排序是不会起做用的;重复添加延后载入字段也不会有何不良影响。
你也能够延后载入关联 model 中的字段(前提是你使用 select_related() 载入了关联 model),用法也是用双下划线链接关联字段:
Blog.objects.select_related().defer("entry__lede", "entry__body")
若是你想清除延后载入的设置,只要使用将 None 作为参数传给 defer() 便可:
# Load all fields immediately. my_queryset.defer(None)
有些字段不管你如何指定,都不会被延后加载。好比,你永远不能延后加载主键字段。若是你使用 select_related() 得到关联 model 字段信息,那么你就不能延后载入关联 model 的主键。(若是这样作了,虽然不会抛出错误,事实上却不完成延后加载)
注意
defer() 方法(和随后提到的 only() 方法) 都只适用于特定状况下的高级属性。它们能够提供性能上的优化,不过前提是你已经对你用到的查询有过很深刻细致的分析,很是清楚你须要的到底是哪些信息,并且已经对你所须要的数据和默认状况下返回的全部数据进行比对,清楚二者之间的差别。这完成了上述工做以后,再使用这两种方法进行优化才是有意义的。因此当你刚开始构建你的应用时,先不要急着使用 defer() 方法,等你已经写完查询而且分析成哪些方面是热点应用之后,再用也不迟。
only(*fields)
only() 方法或多或少与 defer() 的做用相反。若是你在提取数据时但愿某个字段不该该被延后载入,而应该当即载入,那么你就能够作使用 only() 方法。若是你一个 model ,你但愿它全部的字段都延后加载,只有某几个字段是当即载入的,那么你就应该使用 only() 方法。
若是你有一个 model,它有 name, age 和 biography 三个字段,那么下面两种写法效果同样的:
Person.objects.defer("age", "biography") Person.objects.only("name")
你不管什么时候调用 only(),它都会马上更改载入设置。这与它的命名很是相符:只有 only 中的字段会当即载入,而其余的则都是延后载入的。所以,连续调用 only() 时,只有最后一个 only 方法才会生效:
# This will defer all fields except the headline. Entry.objects.only("body", "lede").only("headline")
因为 defer() 能够递增(每次都添加字段到延后载入的列表中),因此你能够将 only() 和 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")
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(nowait=False)
返回一个 queryset ,会锁定相关行直到事务结束。在支持的数据库上面产生一个SELECT ... FOR UPDATE 语句
例如:
entries = Entry.objects.select_for_update().filter(author=request.user)
全部匹配的行将被锁定,直到事务结束。这意味着能够经过锁防止数据被其它事务修改。
通常状况下若是其余事务锁定了相关行,那么本查询将被阻塞,直到锁被释放。若是这不是你想要的行为,请使用select_for_update(nowait=True). 这将使查询不阻塞。若是其它事务持有冲突的锁, 那么查询将引起 DatabaseError 异常.
目前 postgresql_psycopg2, oracle 和 mysql 数据库后端 select_for_update(). 可是 MySQL 不支持 nowait 参数。显然,用户应该检查后端的支持状况。
当在不支持nowait功能的数据库后端(例如 MySql) 使用nowait=True 参数调用 select_for_update() 时将引起 DatabaseError 异常. 这是防止意外形成代码被阻塞。
在自动提交模式下使用 select_for_update() 将引起 TransactionManagementError 异常,缘由是自动提交模式下不支持锁定行。若是容许这个调用,那么可能形成数据损坏,并且这个功能很容易在事务外被调用。
对于不支持 SELECT ... FOR UPDATE 的后端 (例如SQLite) select_for_update() 将没有效果。
raw(raw_query, params=None, translations=None)
Changed in Django 1.7:
raw 移动到QuerySet 类中。之前,它只位于Manager 中。
接收一个原始的SQL 查询,执行它并返回一个django.db.models.query.RawQuerySet 实例。这个RawQuerySet 实例能够迭代以提供实例对象,就像普通的QuerySet 同样。
更多信息参见执行原始的SQL 查询。
警告
raw() 永远触发一个新的查询,而与以前的filter 无关。所以,它一般应该从Manager 或一个全新的QuerySet 实例调用。
这些方法每次被调用的时候都会查询数据库。
get(**kwargs)
返回按照查询参数匹配到的对象,参数的格式应该符合 Field lookups的要求.
若是匹配到的对象个数不仅一个的话,get() 将会触发MultipleObjectsReturned 异常. MultipleObjectsReturned 异常是模型类的属性.
若是根据给出的参数匹配不到对象的话,get() 将触发DoesNotExist 异常. 这个异常是模型类的属性. Example:
Entry.objects.get(id='foo') # raises Entry.DoesNotExist The DoesNotExist exception inherits from django.core.exceptions.ObjectDoesNotExist, so you can target multiple DoesNotExist exceptions. Example: 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.")
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(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(defaults) obj = self.model(**params) obj.save()
它表示从非'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 强制要求惟一性(参见unique 和 unique_together),这个方法容易致使竞态条件可能会仍具备相同参数的多行同时插入。
若是你正在使用MySQL,请确保使用READ COMMITTED 隔离级别而不是默认的REPEATABLE READ,不然你将会遇到get_or_create 引起IntegrityError 但对象在接下来的get() 调用中并不存在的状况。
最后讲一句get_or_create() 在Django 视图中的使用。请确保只在POST 请求中使用,除非你有充分的理由。GET 请求不该该对数据有任何影响。而POST 则用于对数据产生影响的请求。更多信息,参见HTTP 细则中的安全的方法。
警告
你能够经过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 字段是惟一的它仍然不能建立。
update_or_create(defaults=None, **kwargs)
New in Django 1.7.
一个经过给出的kwargs 来更新对象的便捷方法, 若是须要的话建立一个新的对象。defaults 是一个由 (field, value) 对组成的字典,用于更新对象。
返回一个由 (object, created)组成的元组,元组中的object 是一个建立的或者是被更新的对象, created 是一个标示是否建立了新的对象的布尔值。
update_or_create 方法尝试经过给出的kwargs 去从数据库中获取匹配的对象。若是找到匹配的对象,它将会依据defaults 字典给出的值更新字段。
这用做样板代码的一种快捷方式。例如:
try: obj = Person.objects.get(first_name='John', last_name='Lennon') for key, value in updated_values.iteritems(): setattr(obj, key, value) obj.save() except Person.DoesNotExist: updated_values.update({'first_name': 'John', 'last_name': 'Lennon'}) obj = Person(**updated_values) obj.save()
若是模型的字段数量较大的话,这种模式就变的很是不易用。上面的示例能够用 update_or_create() 重写:
obj, created = Person.objects.update_or_create( first_name='John', last_name='Lennon', defaults=updated_values)
kwargs 中的名称如何解析的详细描述能够参见get_or_create()。
和上文描述的get_or_create() 同样,这个方式容易致使竞态条件,若是数据库层级没有前置惟一性它会让多行同时插入。
bulk_create(objs, batch_size=None)
使用django orm大批量插入的时候咱们能够不使用for循环对一个一个的save而是使用
bulk_create来批量插入
例如:
>>> Entry.objects.bulk_create([ ... Entry(headline="Django 1.0 Released"), ... Entry(headline="Django 1.1 Announced"), ... Entry(headline="Breaking: Django is awesome") ... ])
count()
返回在数据库中对应的 QuerySet.对象的个数。 count() 永远不会引起异常。
Example:
# 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()
接收一个主键值列表,而后根据每一个主键值所其对应的对象,返回一个主键值与对象的映射字典。
例如:
>>> 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([]) {}
若是你给 in_bulk() 传递的是一个空列代表,获得就是一个空字典。
iterator()
运行查询(QuerySet),而后根据结果返回一个 迭代器(iterator。 作为比较,使用 QuerySet 时,从数据库中读取全部记录后,一次性将全部记录实例化为对应的对象;而 iterator() 则是读取记录后,是分屡次对数据实例化,用到哪一个对象才实例化哪一个对象。相对于一次性返回不少对象的 QuerySet,使用迭代器不只效率更高,并且更节省内存。
要注意的是,若是将 iterator() 做用于 QuerySet,那就意味着会再一次运行查询,就是说会运行两次查询。
latest(field_name=None)
根据时间字段 field_name 获得最新的对象。
下面这个例子根据 pub_date 字段获得数据表中最新的 Entry 对象:
Entry.objects.latest('pub_date')
若是你在 model 中 Meta 定义了 get_latest_by 项, 那么你能够略去 field_name 参数。Django 会将 get_latest_by 作为默认设置。
和 get(), latest() 同样,若是根据所给条件没有找到匹配的对象,就会抛出 DoesNotExist 异常。
注意 latest() 是纯粹为了易用易读而存在的方法。
earliest(field_name=None)
一种相似latest()的查询
first()
返回结果集的第一个对象, 当没有找到时返回None.若是 QuerySet 没有设置排序,则将会自动按主键进行排序
Example:
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()
工做方式相似first(),只是返回的是查询集中最后一个对象。
aggregate(*args, **kwargs)
返回一个字典,包含根据QuerySet 计算获得的聚合值(平均数、和等等)。aggregate() 的每一个参数指定返回的字典中将要包含的值。
Django 提供的聚合函数在下文的聚合函数中讲述。由于聚合也是查询表达式,你能够组合多个聚合以及值来建立复杂的聚合。
使用关键字参数指定的聚合将使用关键字参数的名称做为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}
聚合的深刻讨论,参见聚合的指南。
exists()
若是QuerySet 包含任何结果,则返回True,不然返回False。它会试图用最简单和最快的方法完成查询,但它执行的方法与普通的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")
... 但不会快不少(由于这须要很大的QuerySet 以得到效率的提高)。
另外,若是some_queryset 尚未求值,但你知道它将在某个时刻求值,那么使用some_queryset.exists() 将比简单地使用bool(some_queryset) 完成更多的工做(一个查询用于存在性检查,另一个是后面的求值),后者将求值并检查是否有结果返回。
update(**kwargs)
更新操做
例如:
>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)
更新特定的数据
>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False, headline='This is old')
不能对外键进行更新操做
>>> Entry.objects.update(blog__name='foo') # Won't work!
能够经过外键进行更新
>>> Entry.objects.filter(blog__id=1).update(comments_on=True)
下面是更新的变种方法
e = Entry.objects.get(id=10) e.comments_on = False e.save()
上面的语句相似下面的语句:
Entry.objects.filter(id=10).update(comments_on=False)
delete
delete()
删除操做
例如:
>>> b = Blog.objects.get(pk=1)
删除全部知足条件的
>>> Entry.objects.filter(blog=b).delete()
上面操做相似于下面语句:
blogs = Blog.objects.all() # This will delete all Blogs and all of their Entry objects. blogs.delete()
classmethod as_manager()
New in Django 1.7.
类方法返回一个管理器实例。
字段查询是指如何指定SQL WHERE子句的内容. 它们经过查询集的filter(), exclude() and get()的关键字参数指定.
精确匹配。
Examples:
Entry.objects.get(id__exact=14) Entry.objects.get(id__exact=None) SQL equivalents: SELECT ... WHERE id = 14; SELECT ... WHERE id IS NULL;
不区分大小写的精确匹配
例如:
Blog.objects.get(name__iexact='beatles blog') Blog.objects.get(name__iexact=None) SQL equivalents: SELECT ... WHERE name ILIKE 'beatles blog'; SELECT ... WHERE name IS NULL;
模糊匹配.
例如:
Entry.objects.get(headline__contains='Lennon') SQL equivalent: SELECT ... WHERE headline LIKE '%Lennon%';
不区分大小写的模糊匹配
例如:
Entry.objects.get(headline__icontains='Lennon') SQL equivalent: SELECT ... WHERE headline ILIKE '%Lennon%';
至关于数据库的in查询.
例如:
Entry.objects.filter(id__in=[1, 3, 4]) SQL equivalent: SELECT ... WHERE id IN (1, 3, 4);
你也能够动态生成list进行in查询:
inner_qs = Blog.objects.filter(name__contains='Cheddar') entries = Entry.objects.filter(blog__in=inner_qs)
上面的语句相似于下面的sql语句:
SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')
若是使用ValuesQuerySet 查询,确保只选择一个列:
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)
大于
例子:
Entry.objects.filter(id__gt=4) SQL语句至关于: SELECT ... WHERE id > 4;
大于或等于
小于
小于或等于
区分大小写,开始位置匹配
例如:
Entry.objects.filter(headline__startswith='Will') SQL equivalent: SELECT ... WHERE headline LIKE 'Will%';
SQLite 不支持区分大小写 LIKE 语句; Sqlite 下startswith 等于 istartswith .
不区分大小写,开始位置匹配
例如:
Entry.objects.filter(headline__istartswith='will') SQL equivalent: SELECT ... WHERE headline ILIKE 'Will%';
以什么结尾.
例如:
Entry.objects.filter(headline__endswith='cats') SQL equivalent: SELECT ... WHERE headline LIKE '%cats';
以什么结尾不区分大小写.
例如:
Entry.objects.filter(headline__iendswith='will') SQL equivalent: SELECT ... WHERE headline ILIKE '%will'
范围查询,相似于sql的between and.
Example:
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 equivalent: SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';
对日期/时间字段精确匹配年分,年分用四位数字表示。
例如:
Entry.objects.filter(pub_date__year=2005)
等价于 SQL:
SELECT ... WHERE EXTRACT('year' FROM pub_date) = '2005';
(不一样的数据库引擎中,翻译获得的 SQL 也不尽相同。)
对日期/时间字段精确匹配月分,用整数表示月分,好比 1 表示一月,12 表示十二月。
例如:
Entry.objects.filter(pub_date__month=12)
等价于 SQL:
SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12';
(不一样的数据库引擎中,翻译获得的 SQL 也不尽相同。)
对于日期和日期时间字段,具体到某一天的匹配。取一个整数的天数。
Example:
Entry.objects.filter(pub_date__day=3) SQL equivalent: SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';
对日期/时间字段匹配星期几
例如:
Entry.objects.filter(pub_date__week_day=2)
等价于 SQL:
SELECT ... WHERE EXTRACT('dow' FROM pub_date) = '2';
(不一样的数据库引擎中,翻译获得的 SQL 也不尽相同。)
要注意的是,这段代码将获得 pub_date 字段是星期一的全部记录 (西方习惯于将星期一看作一周的次日),与它的年月信息无关。星期以星期天作为第一天,以星期六作为最后一天。
对于小时的匹配,取值只能是0到23之间.
例如:
Event.objects.filter(timestamp__hour=23) SQL equivalent: SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23';
对于分钟的匹配,取值只能是0到59之间.
例如:
Event.objects.filter(timestamp__minute=29) SQL equivalent: SELECT ... WHERE EXTRACT('minute' FROM timestamp) = '29';
对于秒的匹配,取值只能是0到59之间.
例如:
Event.objects.filter(timestamp__second=31) 等同于SQL语句: SELECT ... WHERE EXTRACT('second' FROM timestamp) = '31';
值为 True 或 False, 至关于 SQL语句IS NULL和IS NOT NULL.
例如:
Entry.objects.filter(pub_date__isnull=True) SQL equivalent: SELECT ... WHERE pub_date IS NULL;
一个Boolean类型的全文搜索,以全文搜索的优点。这个很像 contains ,可是因为全文索引的优点,以使它更显著的快。
Example:
Entry.objects.filter(headline__search="+Django -jazz Python") SQL equivalent: SELECT ... WHERE MATCH(tablename, headline) AGAINST (+Django -jazz Python IN BOOLEAN MODE);
正则表达式的匹配规则
例如:
Entry.objects.get(title__regex=r'^(An?|The) +') SQL equivalents: 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
正则表达式的匹配规则,忽略大小写
例如:
Entry.objects.get(title__iregex=r'^(an?|the) +') SQL equivalents: 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 模块提供如下聚合函数。关于如何使用这些聚合函数的细节,参见聚合函数的指南。关于如何建立聚合函数,参数聚合函数 的文档。
警告
SQLite 不能直接处理日期/时间字段的聚合。这是由于SQLite 中没有原生的日期/时间字段,Django 目前使用文本字段模拟它的功能。在SQLite 中对日期/时间字段使用聚合将引起NotImplementedError。
注
在QuerySet 为空时,聚合函数函数将返回None。 例如,若是QuerySet 中没有记录,Sum 聚合函数将返回None 而不是0。Count 是一个例外,若是QuerySet 为空,它将返回0。
全部聚合函数具备如下共同的参数:
引用模型字段的一个字符串,或者一个查询表达式。
New in Django 1.8:
如今在复杂的计算中,聚合函数能够引用多个字段。
用来表示返回值的模型字段,它是一个可选的参数。
New in Django 1.8:
添加output_field 参数。
注
在组合多个类型的字段时,只有在全部的字段都是相同类型的状况下,Django 才能肯定output_field。不然,你必须本身提供output_field 参数。
这些关键字参数能够给聚合函数生成的SQL 提供额外的信息。
class Avg(expression, output_field=None, **extra)
返回给定expression 的平均值,其中expression 必须为数值。
默认的别名:<field>__avg
返回类型:float
class Count(expression, distinct=False, **extra)
返回与expression 相关的对象的个数。
默认的别名:<field>__count
返回类型:int
有一个可选的参数:distinct 若是distinct=True,Count 将只计算惟一的实例。它等同于COUNT(DISTINCT <field>) SQL 语句。默认值为False。
class Max(expression, output_field=None, **extra)
返回expression 的最大值。
默认的别名:<field>__max
返回类型:与输入字段的类型相同,若是提供则为 output_field 类型
class Min(expression, output_field=None, **extra)
返回expression 的最小值。
默认的别名:<field>__min
返回的类型:与输入字段的类型相同,若是提供则为 output_field 类型
class StdDev(expression, sample=False, **extra)
返回expression 的标准差。
默认的别名:<field>__stddev
返回类型:float
有一个可选的参数:
sample
默认状况下,StdDev 返回群体的标准差。可是,若是sample=True,返回的值将是样本的标准差。
SQLite
SQLite 没有直接提供StdDev。有一个可用的实现是SQLite 的一个扩展模块。参见SQlite 的文档 中获取并安装这个扩展的指南。
class Sum(expression, output_field=None, **extra)
计算expression 的全部值的和。
默认的别名:<field>__sum
返回类型:与输入的字段相同,若是提供则为output_field 的类型
class Variance(expression, sample=False, **extra)
返回expression 的方差。
默认的别名:<field>__variance
返回的类型:float
有一个可选的参数:sample 默认状况下,Variance 返回群体的方差。可是,若是sample=True,返回的值将是样本的方差。
SQLite
SQLite 没有直接提供Variance。有一个可用的实现是SQLite 的一个扩展模块。 参见SQlite 的文档 中获取并安装这个扩展的指南。
本节提供查询相关的工具的参考资料,它们其它地方没有文档。
class Q
Q对象(django.db.models.Q)能够对关键字参数进行封装,从而更好地应用多个查询。
通常咱们在Django程序中查询数据库操做都是在QuerySet里进行进行,例以下面代码:
>>> q1 = Entry.objects.filter(headline__startswith="What") >>> q2 = q1.exclude(pub_date__gte=datetime.date.today()) >>> q3 = q1.filter(pub_date__gte=datetime.date.today())
或者将其组合起来,例如:
>>>q1 = Entry.objects.filter(headline_startswith="What").exclude(pub_date_gte=datetime.date.today())
随着咱们的程序愈来愈复杂,查询的条件也跟着复杂起来,这样简单的经过一个filter()来进行查询的条件将致使咱们的查询愈来愈长。
Q()对象就是为了将这些条件组合起来。
当咱们在查询的条件中须要组合条件时(例如两个条件“且”或者“或”)时。咱们可使用Q()查询对象。例以下面的代码
fromdjango.db.modelsimports Q q=Q(question_startswith="What")
这样就生成了一个Q()对象,咱们可使用符号&或者|将多个Q()对象组合起来传递给filter(),exclude(),get()等函数。当多个Q()对象组合起来时,Django会自动生成一个新的Q()。例以下面代码就将两个条件组合成了一个
Q(question__startswith='Who') | Q(question__startswith='What')
使用上述代码可使用SQL语句这么理解:
WHEREquestionLIKE 'Who%' ORquestionLIKE 'What%'
咱们能够在Q()对象的前面使用字符“~”来表明意义“非”,例以下面代码:
Q(question__startswith='Who') | ~Q(pub_date__year=2005)
对应SQL语句能够理解为:
WHEREquestionlike "Who%" ORyear(pub_date) !=2005
这样咱们可使用 “&”或者“|”还有括号来对条件进行分组从而组合成更加复杂的查询逻辑。
也能够传递多个Q()对象给查询函数,例以下面代码:
News.objects,get( Q(question__startswith='Who'), Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) )
多个Q()对象之间的关系Django会自动理解成“且(and)”关系。如上面代码使用SQL语句理解将会是:
SELECT * fromnewsWHEREquestionLIKE 'Who%' AND (pub_date = '2005-05-02' ORpub_date = '2005-05-06')
Q()对象能够结合关键字参数一块儿传递给查询函数,不过须要注意的是要将Q()对象放在关键字参数的前面,看下面代码
#正确的作法
News.objects.get( Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)), question__startswith='Who')
#错误的作法,代码将关键字参数放在了Q()对象的前面。
News.objects.get( question__startswith='Who', Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))