zoukankan      html  css  js  c++  java
  • Django lazy load 懒加载 倒序查询

    Django orm默认懒加载
      ###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') 等语句时。 #####并没有真正去数据库操作取出、生成数据,而是生成Query_set迭代对象  .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)] 的区别 前者是一个生成器对象,当需要数据时,根据规则去生成,而后者是实实在在在内存中存在的大列表  
    2.2 升降序
    ####.order_by()语句 order_by('id')’默认升序 ASC ####在order_by('-id')和order_by('-pub_time') 排序字段名前加 - 减号表示降序 DESC res = models.Article.objects.all().order_by('id') 按照id正向排序 - ####reverse()方法反向排序 res.reverse()[:5] 注意,这与Python 中从一个序列的末尾进行切片有点不一样。上面的例子将首先返回最后一个元素,然后是倒数第二个元素,依此类推。如果我们有一个Python序列,当我们查看list[-5:]时,我们将一下子得到倒数五个元素。Django不支持这种访问模型(从末尾进行切片),因为它不可能利用SQL高效地实现。   同时还要注意,reverse() 应该只在一个已经定义排序的QuerySet上调用(例如,在一个定义了默认排序的模型上,或者使用order_by()的时候)。如果QuerySet没有定义排序,调用reverse()将不会有任何效果
    三、倒序查询
    ###本来这片文章的起因就是作者在写一个查询语句,我只需要最后更新的10个数据。我就在想如果是用SQL语句很简单: 但是如果使用Query_set 来查询,不管我是正序还是倒序,都会返回巨大的数据量。就开始去了解Django的Query_set 查询策略
    from django.db import models
    
    class Article(models.Model):
        
        title = models.CharField(max_length= 64)
        body = models.TextField()
        pub_time = models.DateTimeField(auto_now_add= True)
    
        class Meta:
            get_latest_by = 'pub_time'
    
    • 几种反向查询策略:以上表为例

    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()

    3.2 访问最后一个元素
    - 通过.frist()访问第一个元素,.last()访问最后一个元素. models.Article.objects.all().last()
    • latest(self, *fields, field_name=None) 函数访问

    根据 model 的 'get_latest_by' 选项或可选的字段名参数返回最新的对象. 例子:
     
    Article.objects.latest()
     
    Article.objects.latest('expire_date')

    如果模型的Meta指定get_latest_by,则可以将field_name参数留给earliest()或者 latest()。默认情况下,Django将使用get_latest_by中指定的字段。

    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))

    等价SQL:

    SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';

    year、month、day

    year: 返回精确的年份

    例如:

    Entry.objects.filter(pub_date__year=2005)

    等价SQL:

    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)

    等价SQL:

    SELECT ... WHERE pub_date IS NULL;

  • 相关阅读:
    第三章 AjaxPro框架
    第一章 ASP.NET XML与JSON
    第二章 ASP.NET Ajax核心对象
    第五次作业
    第四次作业
    第三周笔记
    第二周笔记
    Java作业
    日期顺时,自动跳过节假日
    利用java实现excel转pdf文件
  • 原文地址:https://www.cnblogs.com/shiqi17/p/9621878.html
Copyright © 2011-2022 走看看