• Django ORM返回QuerySets的某些函数


    整个Django框架,如果要问喜欢那部分,我首先想到的就是它的ORM;Django集成的ORM好用,秉承了Pythonic的理念,还有很浓的OO味道。单个看ORM的函数,似乎是管中窥豹,如果你把各种函数组合起来写,你会发现,原来也可以这么用的,太酷了吧?但还是单独看看这些函数的,等你逐个了解了,一气呵成的感觉就有了。

    拾遗,随意拿些函数来说说,读者只需了解,理念就形成了,有兴趣的稍微记忆下,就是自己的东西了。

    1.annotate
    说到annotate,不能提到聚合aggregate(Avg,Count,Max,Min...),因为annotate需要结合这些聚合函数,才能发挥它的作用,比如博客应用,博客和博客的回复Commnet,取出博客列表的同时,你如果也要取出回复的条数,应该怎么写呢:
    blogs = Blog.objects.annotate(Count('commnet'))

    这回取出博客列表的同时,也能取到相应的回复条数了。template中怎么取值:
    {%for blog in blogs%}
    {{blog.comment__count}}
    {%endfor%}

    你也可以该字段给个别名:
    blogs = Blog.objects.annotate(comment_count=Count('commnet'))

    这个函数,如果结合filter exclude get,出来的效果你懂的!

    2 values
    values是返回QuerySet吗?严格说是ValuesQuerySet,是QuerySet的子集。看代码:
    Blog.objects.values()

    得出的是:
    [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'},...]
    没有指定参数,默认会返回全部的字段字典列表。指定参数:
    Blog.objects.values('id', 'name')
    得出:
    [{'id': 1, 'name': 'Beatles Blog'}]
    在template里使用它 只需把它当成一个iterable,循环取值即可,每条记录就是一个字典,记录的属性就是实体的属性字段。
    值得注意的是它返回的是ValuesQuerySet,而不是QuerySet,如果你使用了values()后,再使用QuerySet的函数如filter,出现什么问题,你可以试试。

    3 dates
    顾名思义,dates是和时间有关的函数,用法:
    Entry.objects.dates('pub_date', 'year')

    结果:

    [datetime.datetime(2005, 1, 1),...]

    得出的是时间datetime列表,和values函数相似,得出的是QuerySet的子集:DateQuerySet;这个函数不好理解,如上面的Entry.objects.dates('pub_date', 'year'),是什么意思呢?
    其实就是取出所有博客的时间列表,参数‘year’,出来的时间列表 是以年份为依据,不会有重复年份,月份和日期默认是1;比如众多blog中,有几万条,发表时间当然不止同一年的,该语句出来 :
    [datetime.datetime(2005, 1, 1),datetime.datetime(2006, 1, 1),datetime.datetime(2007, 1, 1),datetime.datetime(2008, 1, 1),...]
    嗯,时间列表,在template用,你应该知道了!

    参数 field kind order,形如:
    Entry.objects.dates('pub_date', 'day', order='DESC')
    field就是实体的一个时间字段,kid就是 year month day,order就是排序 desc asc,好理解吧?

    如果你还有疑问:我们想取出博客的所有月份,怎么写? 呃,试试这样:

    Blog.objects.dates('pub_date', 'month', order='DESC')...

    结果:

    [datetime.datetime(2005, 1, 1),datetime.datetime(2005, 2, 1),... ,datetime.datetime(2006, 4, 1),...,datetime.datetime(2008, 6, 1),...]

    但如果想取所有日期列表呢?唉,有必要吗?dates用途,你平时见到的归档 都是按照年份或者月份归档的,如果按照日期归档,该网站的文摘更新速度不是一般的快哦!还是有办法的:
    Blog.objects.dates('pub_date', 'day', order='DESC')...

    4 defer
    defer是个好函数,有时候一个实体有过多的字段,取实体或者实体列表的时候,占用了多大的内存,而你却不需要取出全部的字段,比如博客的正文内容,你不需要立即检索数据库,这时defer就是你需要的东西。defer函数与前面讲的values有区别的,前者返回的是ValuesQuerySet,而defer返回的是QuerySet对象,这意味着,使用了defer后,你还可以结合QuerySet其他的函数,让整个语句结合更多的条件;Django的ORM除了做得OO,还很注重性能的。
    如果取博客的文章列表,让容量很大的正文和副标题在数据库层不进行检索,看看代码:
    Blog.objects.defer("content", "subtitle")

    defer的用法还比较多,比如:
    my_queryset=Blog.objects.select_related().defer("commnet__content", "commnet__pic")

    以上的语句说明,获取博客表和回复表,他们两表是使用了内连接,获取的时候,让回复表不检索回复内容和图片。select_related之前记得有说过,是一次性表关联。

    如果你想再原来语句获取到的实体列表上取消某些字段的延时,可以通过这样的用法取消延时,让数据库立即检索全部字段:
    my_queryset.defer(None)

    还有很多的defer组合用法,需要自己去慢慢体会了。

    5 only
    only很多程度上和defer是同一类的东西,可以理解为defer的相反函数吧。比如Person实体里有三个字段:name age birthday,下面这两条语句是等价的:

    Person.objects.defer("age", "biography")
    Person.objects.only("name")

  • 相关阅读:
    Django基础之cookie
    Django基础之redirect()
    Django基础之render()
    Django基础之JsonResponse对象
    Django基础之response对象
    scrapy框架自定制命令
    数据分析案例-拉勾网招聘信息
    爬虫之单线程多任务异步抓取
    数据分析之matplotlib使用
    数据分析之numpy使用
  • 原文地址:https://www.cnblogs.com/ykugb/p/9517517.html
Copyright © 2020-2023  润新知