Django框架 querySet功能解析

可切片

使用Python 的切片语法来限制查询集记录的数目 。它等同于SQL 的LIMIT 和OFFSET 子句。

>>> Entry.objects.all()[:5] # (LIMIT 5)
Entry.objects.all()[5:10] # (OFFSET 5 LIMIT 5)

不支持负的索引(例如Entry.objects.all()[-1])。通常,查询集 的切片返回一个新的查询集 —— 它不会执行查询。   

可迭代

articleList=models.Article.objects.all()
for article in articleList:
  print(article.title) 

惰性查询

查询集 是惰性执行的 —— 创建查询集不会带来任何数据库的访问。你可以将过滤器保持一整天,直到查询集 需要求值时,Django 才会真正运行这个查询。

queryResult=models.Article.objects.all() # not hits database
print(queryResult) # hits database
for article in queryResult:
  print(article.title)  # hits database

一般来说,只有在“请求”查询集 的结果时才会到数据库中去获取它们。当你确实需要结果时,查询集 通过访问数据库来求值。 关于求值发生的准确时间,参见何时计算查询集。  

缓存机制

每个查询集都包含一个缓存来最小化对数据库的访问。理解它是如何工作的将让你编写最高效的代码。

在一个新创建的查询集中,缓存为空。首次对查询集进行求值 —— 同时发生数据库查询 ——Django 将保存查询的结果到查询集的缓存中并返回明确请求的结果(例如,如果正在迭代查询集,则返回下一个结果)。接下来对该查询集 的求值将重用缓存的结果。

请牢记这个缓存行为,因为对查询集使用不当的话,它会坑你的。例如,下面的语句创建两个查询集,对它们求值,然后扔掉它们:

print([a.title for a in models.Article.objects.all()])
print([a.create_time for a in models.Article.objects.all()])

这意味着相同的数据库查询将执行两次,显然倍增了你的数据库负载。同时,还有可能两个结果列表并不包含相同的数据库记录,因为在两次请求期间有可能有Article被添加进来或删除掉。为了避免这个问题,只需保存查询集并重新使用它: 

queryResult=models.Article.objects.all()
print([a.title for a in queryResult])
print([a.create_time for a in queryResult])

何时查询集不会被缓存?

查询集不会永远缓存它们的结果。当只对查询集的部分进行求值时会检查缓存, 如果这个部分不在缓存中,那么接下来查询返回的记录都将不会被缓存。所以,这意味着使用切片或索引来限制查询集将不会填充缓存。

例如,重复获取查询集对象中一个特定的索引将每次都查询数据库:

>>> queryset = Entry.objects.all()
>>> print queryset[5] # Queries the database
>>> print queryset[5] # Queries the database again

然而,如果已经对全部查询集求值过,则将检查缓存:  

>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset] # Queries the database
>>> print queryset[5] # Uses cache
>>> print queryset[5] # Uses cache

下面是一些其它例子,它们会使得全部的查询集被求值并填充到缓存中:

>>> [entry for entry in queryset]
>>> bool(queryset)
>>> entry in queryset
>>> list(queryset)

注:简单地打印查询集不会填充缓存。  

queryResult=models.Article.objects.all()
print(queryResult) # hits database
print(queryResult) # hits database 

exists()与iterator()方法

exists:

简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些 数据!为了避免这个,可以用exists()方法来检查是否有数据:

if queryResult.exists():
  #SELECT (1) AS "a" FROM "blog_article" LIMIT 1; args=()
    print("exists...")

iterator:

当queryset非常巨大时,cache会成为问题。

处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统 进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法 来获取数据,处理完数据就将其丢弃。

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,可能 会造成额外的数据库查询。 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Django实现微信小程序的登录验证功能并维护登录态

    这次自己做了一个小程序来玩,在登录方面一直有些模糊,网上看了很多文档后,得出以下一种解决方案. 环境说明: 1.小程序只需要拿到openid,其他信息不存储. 2.Django自带的User类不适合. 具体操作流程: 1.用户点进小程序,就调用wx.login()获取临时登录凭证code, wx.login()用户是无感知的, 2.通过wx.request()将code传到开发者服务器的后台程序, 3.后台拿到code之后,调用微信提供的接口,获取openid和session_key, 4.后台

  • django admin后台添加导出excel功能示例代码

    Django功能强大不单在于他先进的编程理念,很多现有的功能模块更是可以直接拿来使用,比如这个牛掰的admin模块,可以作为一个很好的信息登记管理系统. admin模块中的actioin是可以自定义添加的,比如这次要介绍的导出excel功能,就可以在action中触发. 本文将详细介绍如何导出admin中录入的数据为excel,可以直接提交给你的leader观看. 首先我们要安装 xlwt 这个工具模块: pip install xlwt import的准备 修改admin.py: #-*-co

  • 介绍Python的Django框架中的QuerySets

    Django的QuerySets酷毙了! 在本文中我将解释一下QuerySets是什么,它是如何工作的(如果你对它已经熟悉了,你可以直接跳到第二部分),我认为如果可以的话你应该总是返回QuerySets对象,下面让我来谈谈如何做. QuerySets很酷 QuerySet,本质上是一个给定的模型的对象列表.我说"列表"而不是"组"或更正式的"集合"因为它是有序的.事实上,你可能已经熟悉如何获得QuerySets,因为这就是你调用variousBo

  • python实现合并多个list及合并多个django QuerySet的方法示例

    本文实例讲述了python实现合并多个list及合并多个django QuerySet的方法.分享给大家供大家参考,具体如下: 在用python或者django写一些小工具应用的时候,有可能会遇到合并多个list到一个 list 的情况.单纯从技术角度来说,处理起来没什么难度,能想到的办法很多,但我觉得有一个很简单而且效率比较高的方法是我以前没注意到的.那就是利用 chain 方法来合并多个list. 同样也可以用来合并django 的 QuerySet. 1. python用chain 来合并

  • Python的Django框架中的select_related函数对QuerySet 查询的优化

    1. 实例的背景说明 假定一个个人信息系统,需要记录系统中各个人的故乡.居住地.以及到过的城市.数据库设计如下: Models.py 内容如下: from django.db import models class Province(models.Model): name = models.CharField(max_length=10) def __unicode__(self): return self.name class City(models.Model): name = models

  • django 中QuerySet特性功能详解

    Book表的数据显示 id title price publish_id 2 Linux 30 1 3 项塔兰 45 2 4 追风筝的人 39.9 3 5 富爸爸 23 10 创建queryset 视图 函数, 可以使用的列表的方法,按索引,切片的方法取值,得到一个列表对象 def queryset(request): ret1 = Book.objects.all()[0] #QuerySet支持索引,切片操作 # print(ret1) #linux 得到一个具体的对象 ret2 = Boo

  • Django框架 querySet功能解析

    可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句. >>> Entry.objects.all()[:5] # (LIMIT 5) Entry.objects.all()[5:10] # (OFFSET 5 LIMIT 5) 不支持负的索引(例如Entry.objects.all()[-1]).通常,查询集 的切片返回一个新的查询集 -- 它不会执行查询. 可迭代 articleList=models.Article.obj

  • Django框架用户注销功能实现方法分析

    本文实例讲述了Django框架用户注销功能实现方法.分享给大家供大家参考,具体如下: HttpResponse()里有个delete_cookie()方法专门用来删除cookie 我们到此来完整的实现一下:访问首页如果没有登录,就跳转到登录页面,登录成功之后再跳转回来的过程. 3个方法,index.login.logout # coding:utf-8 from django.shortcuts import render,render_to_response # Create your vie

  • Django框架实现逆向解析url的方法

    本文实例讲述了Django框架实现逆向解析url的方法.分享给大家供大家参考,具体如下: Django中提供了一个关于URL的映射的解决方案,你可以做两个方向的使用: ①. 有客户端的浏览器发起一个url请求,Django根据URL解析,把url中的参数捕获,调用相应的试图,获取相应的数据,然后返回给客户端显示 ②. 通过一个视图的名字,再加上一些参数和值,逆向获取相应的URL 第一个就是平常的请求有URLconf来解析的过程, 第二个叫做,url的逆向解析,url逆向匹配,url的逆向查阅,等

  • Python Django框架url反向解析实现动态生成对应的url链接示例

    本文实例讲述了Python Django框架url反向解析实现动态生成对应的url链接.分享给大家供大家参考,具体如下: url反向解析:根据url路由规则,动态生成对应的url链接 (防止硬编码). url反向解析应用在两个地方:模板中的超链接,视图中的重定向. 项目名/urls.py(项目的url路由配置,url反向解析,取namespace名字): from django.conf.urls import include, url from django.contrib import ad

  • Django框架视图层URL映射与反向解析实例分析

    本文实例讲述了Django框架视图层URL映射与反向解析.分享给大家供大家参考,具体如下: Django视图层主要工作就是衔接HTTP请求.python程序.HTML模板. URL分发(URL dispatcher)映射配置可以被看作Django项目的入口配置(项目下的urls.py以及应用的下的urls.py,include将两者联系起来在项目下的urls.py),通过URLdispatcher可以指定用户的每一个访问的后台的python处理函数是什么. 1.普通url映射 每一个Django

  • Django框架反向解析操作详解

    本文实例讲述了Django框架反向解析操作.分享给大家供大家参考,具体如下: 1. 定义: 随着功能的增加会出现更多的视图,可能之前配置的正则表达式不够准确,于是就要修改正则表达式,但是正则表达式一旦修改了,之前所有对应的超链接都要修改,真是一件麻烦的事情,而且可能还会漏掉一些超链接忘记修改,有办法让链接根据正则表达式动态生成吗? 就是用反向解析的办法. 2. 应用范围: 模板中的超链接 视图中的重定向 3. 使用方法: 定义url时,需要为include定义namespace属性,为url定义

  • Django框架登录加上验证码校验实现验证功能示例

    本文实例讲述了Django框架登录加上验证码校验实现验证功能.分享给大家供大家参考,具体如下: 验证码生成函数 pip install Pillow # /verify_code def verif_ycode(request): #引入绘图模块 from PIL import Image, ImageDraw, ImageFont #引入随机函数模块 import random #定义变量,用于画面的背景色.宽.高 bgcolor = (random.randrange(20, 100), r

  • Django框架使用内置方法实现登录功能详解

    本文实例讲述了Django框架使用内置方法实现登录功能.分享给大家供大家参考,具体如下: 一 内置登录退出思维导图 二 Django内置登录方法 1 位置 2 源码 @deprecate_current_app @sensitive_post_parameters() @csrf_protect @never_cache # 视图函数要渲染的模板位置(registration/login.html) def login(request, template_name='registration/l

  • django框架实现一次性上传多个文件功能示例【批量上传】

    本文实例讲述了django框架实现一次性上传多个文件功能.分享给大家供大家参考,具体如下: 在用django 写文件上传的时候,从request.FILES['myfiles'] 获取到的文件始终只有一个, 但在HTML页面上明明用 HTML5 的 文件控件选择了多个文件,用的是CHROME  浏览器,一次可以选择多个文件上传.在 Pydev 开启debug模式,查看request 对象,发现上传的多个文件确实在request对象中,但为什么 用request.FILES['myfiles']

  • Django框架静态文件使用/中间件/禁用ip功能实例详解

    本文实例讲述了Django框架静态文件使用/中间件/禁用ip功能.分享给大家供大家参考,具体如下: 静态文件 一.静态文件的使用 静态文件:网页中使用的css,js,图片 静态文件的使用: 在项目下创建静态目录,比如:static,导入静态文件(HTML.CSS.js) 在setting.py中配置静态目录 # 通过此url来引用静态文件,可以隐藏服务器的文件的实际保存目录 STATIC_URL = '/abc/' # 指定静态文件所在的物理目录 STATICFILES_DIRS = [os.p

随机推荐