Django框架 之 querySet详解
Django框架 之 querySet详解
浏览目录
可切片
可迭代
惰性查询
缓存机制
exists()与iterator()方法
QuerySet
可切片
使用Python 的切片语法来限制查询集记录的数目 。它等同于SQL 的LIMIT 和OFFSET 子句。
|
1
|
>>> Entry.objects.all()[:5] # (LIMIT 5) |
|
1
|
Entry.objects.all()[5:10] # (OFFSET 5 LIMIT 5) |
不支持负的索引(例如Entry.objects.all()[-1])。通常,查询集 的切片返回一个新的查询集 —— 它不会执行查询。
可迭代
|
1
2
3
4
|
articleList=models.Article.objects.all()for article in articleList: print(article.title) |
惰性查询
查询集 是惰性执行的 —— 创建查询集不会带来任何数据库的访问。你可以将过滤器保持一整天,直到查询集 需要求值时,Django 才会真正运行这个查询。
|
1
2
3
4
5
6
|
queryResult=models.Article.objects.all() # not hits database print(queryResult) # hits database for article in queryResult: print(article.title) # hits database |
一般来说,只有在“请求”查询集 的结果时才会到数据库中去获取它们。当你确实需要结果时,查询集 通过访问数据库来求值。 关于求值发生的准确时间,参见何时计算查询集。
缓存机制
每个查询集都包含一个缓存来最小化对数据库的访问。理解它是如何工作的将让你编写最高效的代码。
在一个新创建的查询集中,缓存为空。首次对查询集进行求值 —— 同时发生数据库查询 ——Django 将保存查询的结果到查询集的缓存中并返回明确请求的结果(例如,如果正在迭代查询集,则返回下一个结果)。接下来对该查询集 的求值将重用缓存的结果。
请牢记这个缓存行为,因为对查询集使用不当的话,它会坑你的。例如,下面的语句创建两个查询集,对它们求值,然后扔掉它们:
|
1
2
|
print([a.title for a in models.Article.objects.all()])print([a.create_time for a in models.Article.objects.all()]) |
这意味着相同的数据库查询将执行两次,显然倍增了你的数据库负载。同时,还有可能两个结果列表并不包含相同的数据库记录,因为在两次请求期间有可能有Article被添加进来或删除掉。为了避免这个问题,只需保存查询集并重新使用它:
|
1
2
3
|
queryResult=models.Article.objects.all()print([a.title for a in queryResult])print([a.create_time for a in queryResult]) |
何时查询集不会被缓存?
查询集不会永远缓存它们的结果。当只对查询集的部分进行求值时会检查缓存, 如果这个部分不在缓存中,那么接下来查询返回的记录都将不会被缓存。所以,这意味着使用切片或索引来限制查询集将不会填充缓存。
例如,重复获取查询集对象中一个特定的索引将每次都查询数据库:
|
1
2
3
|
>>> queryset = Entry.objects.all()>>> print queryset[5] # Queries the database>>> print queryset[5] # Queries the database again |
然而,如果已经对全部查询集求值过,则将检查缓存:
|
1
2
3
4
|
>>> queryset = Entry.objects.all()>>> [entry for entry in queryset] # Queries the database>>> print queryset[5] # Uses cache>>> print queryset[5] # Uses cache |
下面是一些其它例子,它们会使得全部的查询集被求值并填充到缓存中:
|
1
2
3
4
|
>>> [entry for entry in queryset]>>> bool(queryset)>>> entry in queryset>>> list(queryset) |
注:简单地打印查询集不会填充缓存。
|
1
2
3
|
queryResult=models.Article.objects.all()print(queryResult) # hits databaseprint(queryResult) # hits database |
exists()与iterator()方法
exists:
简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些 数据!为了避免这个,可以用exists()方法来检查是否有数据:
|
1
2
3
|
if queryResult.exists(): #SELECT (1) AS "a" FROM "blog_article" LIMIT 1; args=() print("exists...") |
iterator:
当queryset非常巨大时,cache会成为问题。
处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统 进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法 来获取数据,处理完数据就将其丢弃。
|
1
2
3
4
5
6
7
|
objs = Book.objects.all().iterator()# iterator()可以一次只从数据库获取少量数据,这样可以节省内存for obj in objs: print(obj.title)#BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了for obj in objs: print(obj.title) |
当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使 #用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询。
总结:
queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。 使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能 会造成额外的数据库查询。
Django框架 之 querySet详解的更多相关文章
- java的集合框架最全详解
java的集合框架最全详解(图) 前言:数据结构对程序设计有着深远的影响,在面向过程的C语言中,数据库结构用struct来描述,而在面向对象的编程中,数据结构是用类来描述的,并且包含有对该数据结构操作 ...
- spring框架 AOP核心详解
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...
- TP框架I方法详解
TP框架I方法详解 I方法是ThinkPHP众多单字母函数中的新成员,其命名来自于英文Input(输入),主要用于更加方便和安全的获取系统输入变量,可以用于任何地方,用法格式如下:I('变量类型. ...
- RPC框架调用过程详解
RPC框架调用过程详解 2017年09月16日 21:14:08 荷叶清泉 阅读数 6275 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. ...
- 手把手撸套框架-Victory框架1.1 详解
目录 上一篇博客 Victory框架1.0 详解 有说道,1.0的使用过程中出现不少缺点,比如菜单不能折叠,权限没有权限组等等. 所以,我还是抽出时间在下班后,回到我的小黑屋里 完成了1.1的升级. ...
- Django(41)详解异步任务框架Celery
celery介绍 Celery是由Python开发.简单.灵活.可靠的分布式任务队列,是一个处理异步任务的框架,其本质是生产者消费者模型,生产者发送任务到消息队列,消费者负责处理任务.Celery ...
- Django url配置 正则表达式详解 分组命名匹配 命名URL 别名 和URL反向解析 命名空间模式
Django基础二之URL路由系统 本节目录 一 URL配置 二 正则表达式详解 三 分组命名匹配 四 命名URL(别名)和URL反向解析 五 命名空间模式 一 URL配置 Django 1.11版本 ...
- Django学习笔记之Django Form表单详解
知识预览 构建一个表单 在Django 中构建一个表单 Django Form 类详解 使用表单模板 回到顶部 构建一个表单 假设你想在你的网站上创建一个简单的表单,以获得用户的名字.你需要类似这样的 ...
- spring mvc 框架搭建及详解
现 在主流的Web MVC框架除了Struts这个主力 外,其次就是Spring MVC了,因此这也是作为一名程序员需要掌握的主流框架,框架选择多了,应对多变的需求和业务时,可实行的方案自然就多了.不 ...
随机推荐
- 【HDU】4632 Palindrome subsequence(回文子串的个数)
思路:设dp[i][j] 为i到j内回文子串的个数.先枚举所有字符串区间.再依据容斥原理. 那么状态转移方程为 dp[i][j] = dp[i][j-1] + dp[i+1][j] - dp[i+ ...
- cookie跨站脚本漏洞解决方案
近日项目碰到一个跨脚本注入的问题: 这安全测评工具也是厉害了,直接将脚本注入到cookie里头,以前没有碰到这样的情况. 之前写过一篇文章过滤跨脚本注入的问题.<浅谈XSS攻击原理与解决方法&g ...
- nginx虚拟主机的配置
nginx虚拟主机的配置 server { listen ; server_name 127.0.0.1; access_log off; root /var/www/html/; location ...
- git diff的使用
有时候可能睡觉时候忘记关电脑了,然后不小心触碰到键盘上某个神秘的按钮了,然后自己也不知道就提交了 就可能很悲剧 那么有时候不知道自己是否改变了哪些文件的内容 这时候就需要用到git diff git ...
- 【转】 Pro Android学习笔记(九六):AsyncTask(5):横竖屏切换问题
目录(?)[-] 横竖屏切换的问题 WeakReference 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flow ...
- 关于ESXI能虚拟出多少个虚拟机和CPU的关系
当你的虚拟机报如下错误的时候: esxi5.0版本最高配置: https://www.vmware.com/content/dam/digitalmarketing/vmware/zh-cn/pdf/ ...
- composer 发布自己的开源软件
首先创建一个github项目. 在项目中,创建一个composer.json文件. { "name": "jiqing9006/valid", "de ...
- .Net 框架实现AOP(动态代理实现AOP,本文为翻译)
在上一节,我们将静态实现AOP,但是对于一个大型项目,要想为每个类,每个方法都去实现AOP ,进行日志记录和权限验证似乎是不可能的. 即使可能对于成百上千个类维护,也是很难维护.所以今天的主题就是如标 ...
- python's fifteenth day for me 递归函数
递归... def age(n): if n == 1: return 18 else: return age(n-1)+2 # 反复调用函数age() print(age(4)) l = [1,3, ...
- Python Twisted系列教程12:改进诗歌下载服务器
作者:dave@http://krondo.com/a-poetry-transformation-server/ 译者:杨晓伟(采用意译) 你可以从这里从头阅读这个系列. 新的服务器实现 这里我们 ...