###Django orm默认使用的懒加载,即使用的时候才去访问数据库,且每次默认取最少的数据,当然这样有好处也有坏处...
会导致频繁的查询数据库,如涉及到外键的时候,会先去取需要的数据集,再取外键的数据集,等于访问了两次数据库,那取n条数据就访问了n*n次数据库
如查询语句:
models.Article.objects.all() 当Article表中关联author、tag、categroy等外键字段时,你取一条数据,他需要去访问4次数据库,三外键加本身。
显然的当你执行:
models.Article.objects.all() 这样的语句,如果一次全部查询把所有数据给你返回,你是小网站,数据小无所谓,数据大了内存就爆炸了!
####django orm的策略是,懒加载:
#####即:res = models.Article.objects.all()这样的所有查询、obj = models.Article('title'='xxx', 'body' = 'xxx') 等语句时。
#####
.create() 和.update()语句会保存的同时直接去数据库创建
而在执行res[0].title、res[10],body 还有obj.save()这样的语句时才真正的去执行SQL语句,操作数据库,取数据,保存数据。
第一个很直观的一堆Query_set对象中没有取回数据,当然占用内存就小很多了。
而当每次查询回来数据,Django就会把这些数据保存在cache中,当你下次使用时,不会去数据库再次查询,而是去cache里面取。
- ####结果集
Django 的数据查询基于构建结果集及对结果集进行取值. 结果集是独立于数据库的符合某个查询条件的一组数据对象的集合.这是一个惰性集合:在对该集合取值之前,无法知道该集合有哪些成员.
要生成一个满足你需求的结果集,首先要得到一个描述给定类型的所有对象的初始结果集.这个初始结果集可以通过一系列函数进行更精细的优化处理.当经过处理后的结果集符合你的要求时, 就可以对它进行取值操作(使用迭代操作,slicing操作,或一系列其它技术), 以得到一个你需要的对象或对象的列表.
获得初始结果集
每个 Django model 都有一个与生俱来的管理器对象 objects, 管理器最重要的角色就是作为初始结果的来源. 一个管理器就是一个描述给定类型所有对象的特殊的初始结果集. Article.objects 就是包含所有 Poll 对象的一个初始结果集. 它唯一特殊之处在于它不能被取值. 要克服此限制, 管理器对象有一个 all() 方法. 该方法生成一个 可以 被取值的初始结果集的拷贝:
res = models.Article.objects.all()
Article.objects.all()[:-11:-1] 取最后10个对象
Article.objects.all()[0:10] 取前10个对象
结果集对象是惰性对象 - 也就是说,他们不是 真正的 包含他们表示对象的集合 (或列表). Python 的协议魔法让结果集看起来是一个可迭代,可切片的对象. 事实上在幕后, Django 使用了缓存技术..
如非要把它们变成列表。那只能强制取值了:
querylist = list(Article.objects.all()) #这儿可以理解为 list(dict.keys())一样的感觉,把
对象变为列表
不过,最好不要这么做,特别是在该集合相当大时. Django 每创建一个对象都需要内存,将占用相当大的内存.
可理解为生成器 genrator = (x for x in range(10000000)) 和列表生成式 list = [i for i in range(100000000)] 的区别
前者是一个生成器对象,当需要数据时,根据规则去生成,而后者是实实在在在内存中存在的大列表
#### order_by('id')’默认升序 ASC
####在order_by('-id')和order_by('-pub_time') 排序字段名前加 - 减号表示降序 DESC
res = models.Article.objects.all().order_by('id') 按照id正向排序
res.reverse()[:5]
注意,这与Python 中从一个序列的末尾进行切片有点不一样。上面的例子将首先返回最后一个元素,然后是倒数第二个元素,依此类推。如果我们有一个Python序列,当我们查看list[-5:]时,我们将一下子得到倒数五个元素。Django不支持这种访问模型(从末尾进行切片),因为它不可能利用SQL高效地实现。
同时还要注意,reverse() 应该只在一个已经定义排序的QuerySet上调用(例如,在一个定义了默认排序的模型上,或者使用order_by()的时候)。如果QuerySet没有定义排序,调用reverse()将不会有任何效果
###本来这片文章的起因就是作者在写一个查询语句,我只需要最后更新的10个数据。我就在想如果是用SQL语句很简单:
但是如果使用Query_set 来查询,不管我是正序还是倒序,都会返回巨大的数据量。就开始去了解Django的Query_set 查询策略
以上表为例
order_by() 语句:
models.Article.objects.all().order_by('-id) 或者 order_by('-pub_time')
反向切片访问:
models.Article.objects.fiter(id__gte=0)[::-1] 完全反向切片
reverse()函数
models.Article.objects.all().order_by('id').reverse()
- 通过.frist()访问第一个元素,.last()访问最后一个元素.
models.Article.objects.all().last()
根据 model 的 'get_latest_by' 选项或可选的字段名参数返回最新的对象. 例子:
Article.objects.latest()
Article.objects.latest('expire_date')
如果模型的meta指定get_latest_by,则可以将field_name参数留给earliest()或者 latest()。默认情况下,Django将使用get_latest_by中指定的字段。
由于Django的管理方法中有个lastest()方法,就是得到最近一行记录。如果你的数据模型中有 DateField 或 DateTimeField 类型的字段,你可以通过这个选项来指定lastest()是按照哪个字段进行选取的。
一个 DateField 或 DateTimeField 字段的名字. 若提供该选项, 该模块将拥有一个 get_latest() 函数以得到 "最新的" 对象(依据那个字段):
exact、iexact
exact:精确匹配。区分大小写
Entry.objects.get(id__exact=14)
Entry.objects.get(id__exact=None)
iexact:不区分大小写的精确匹配
Blog.objects.get(name__iexact='beatles blog')
Blog.objects.get(name__iexact=None)
contains、icontains
contains:包含,大小写敏感
Entry.objects.get(headline__contains='Lennon')
icontains:包含,大小写不明感.
Entry.objects.get(headline__icontains='Lennon')
in
在一个给定的列表中.
Example:
Entry.objects.filter(id__in=[1, 3, 4])
gt、gte、lt、lte
gt:大于
例子:
Entry.objects.filter(id__gt=4)
gte:大于或等于
lt:小于
lte:小于或等于
startswith、istartswith、endswith、iendswith
startswith:区分大小写,开始位置匹配
Entry.objects.filter(headline__startswith='Will')
istartswith:不区分大小写,开始位置匹配
endswith:区分大小写,结束位置匹配
iendswith:不区分大小写,结束位置匹配
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))
SELECT ... WHERe pub_date BETWEEN '2005-01-01' and '2005-03-31';
year、month、day
year: 返回精确的年份
Entry.objects.filter(pub_date__year=2005)
SELECT ... WHERe pub_date BETWEEN '2005-01-01' AND '2005-12-31';
month: 对于月份时间字段,匹配一个整数从1 (January)到 12 (December).
day: 对于日期和日期时间字段,具体到某一天的匹配。取一个整数的天数。
isnull
值为 True 或False, 相当于SQL语句IS NULL和IS NOT NULL.
Entry.objects.filter(pub_date__isnull=True)
本文地址:http://xiaoguoguo.dbeile.cn/quote/103.html
多贝乐 http://xiaoguoguo.dbeile.cn/ , 查看更多