一、QuerySet
1.可切片
使用Python 的切片语法来限制查询集记录的数目 。它等同于SQL 的LIMIT 和OFFSET 子句。
>>> Entry.objects.all()[:5] # (LIMIT 5)
>>> Entry.objects.all()[5:10] # (OFFSET 5 LIMIT 5)
不支持负的索引(例如Entry.objects.all()[-1])。通常,查询集 的切片返回一个新的查询集 —— 它不会执行查询。
2.可迭代
articleList=models.Article.objects.all()for article inarticleList:print(article.title)
View Code
3.惰性查询
查询集 是惰性执行的 —— 创建查询集不会带来任何数据库的访问。直到你用到了查询集,才会访问数据库取值
queryResult=models.Article.objects.all() #not hits database 没有访问数据库
print(queryResult) #hits database 此时才访问数据库
for article inqueryResult:print(article.title) #hits database
4.缓存机制
queryResult=models.Article.objects.all()print([a.title for a inqueryResult])print([a.create_time for a in queryResult])
此时只访问了一次数据库,第二次for取值时是从缓存中取的
但是缓存肯定是有数据限制的,不可能无限的存值,那就用到了下面的 iterator() 方法
5. exists()与iterator()方法
ifqueryResult.exists():#SELECT (1) AS "a" FROM "blog_article" LIMIT 1; args=()
print("exists...")
当queryset非常巨大时,cache会成为问题。
处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统 进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法 来获取数据,处理完数据就将其丢弃。
objs=Book.objects.all().iterator()#iterator()可以一次只从数据库获取少量数据,这样可以节省内存
for obj inobjs:print(obj.title)#BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
for obj inobjs:print(obj.title)
当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使#用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询。
总结:
queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。 使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能 会造成额外的数据库查询。
二、extra
extra(select=None, where=None, params=None,
tables=None, order_by=None, select_params=None)
有些情况下,Django的查询语法难以简单的表达复杂的 WHERE 子句,对于这种情况, Django 提供了 extra() QuerySet修改机制 — 它能在 QuerySet生成的SQL从句中注入新子句
extra可以指定一个或多个 参数,例如 select, whereortables. 这些参数都不是必须的,但是你至少要使用一个!要注意这些额外的方式对不同的数据库引擎可能存在移植性问题.(因为你在显式的书写SQL语句),除非万不得已,尽量避免这样做
参数之select
The select 参数可以让你在 SELECT 从句中添加其他字段信息,它应该是一个字典,存放着属性名到 SQL 从句的映射。
queryResult=models.Article
.objects.extra(select={'is_recent': "create_time > '2017-09-05'"})
结果集中每个 Entry 对象都有一个额外的属性is_recent, 它是一个布尔值,表示 Article对象的create_time 是否晚于2017-09-05.
练习:
#in sqlite:
article_obj=models.Article.objects
.filter(nid=1)
.extra(select={"standard_time":"strftime('%%Y-%%m-%%d',create_time)"})
.values("standard_time","nid","title")print(article_obj)#
参数之where /tables
您可以使用where定义显式SQL WHERE子句 -也许执行非显式连接。您可以使用tables手动将表添加到SQL FROM子句。
where和tables都接受字符串列表。所有where参数均为“与”任何其他搜索条件。
举例来讲:
queryResult=models.Article
.objects.extra(where=['nid in (1,3) OR title like "py%"','nid>2'])