Django中的QuerySet类

Stella981
• 阅读 507

QuerSets类的简单介绍

QuerySet是一个model 类对应的实例集合, 即数据库对应表的子集,可以称为查询集。

QuerySet可以构造过滤切片,通常情况下都不会对数据库造成修改。只有查找的时候才会真正地操作数据库

首先,QuerySet是可以迭代的对象,然后可以使用python的切片方法进行切片操作,返回的依旧是一个QuerySets的对象。

在一个QuerySet对象生成的时候,你可以使用lenlist等函数对对象进行操作,计算出包含对象的长度和转化对象成为列表进行操作

QuerSet 的API函数

    filter(**kwargs)

使用传入的查找的参数(**kwarg)进行查找,返回一个新的QuerySet对象。如果与SQL做映射,相当AND连接了所有条件,参数的格式可以点击链接学习。

    exclude(**kwargs)

与filter类似,但是exclude与SQL做映射,相当给filter映射的SQL外加了一个NOT。

    这个例子最后的结果不包括( 时间晚于2005年1月3日并且headline是"Hello" )   

Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')

    映射到SQL:     

SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')

    这个例子最后结果不包括( 时间晚于2005年1月3日或者headline是"Hello" ) 

Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')

   映射到SQL:

SELECT ...
WHERE NOT pub_date > '2005-1-3'
AND NOT headline = 'Hello'

    通过这两个简单的例子,你应该已经了解了exclude的作用

annotate(*args,**kwargs)

当你需要使用统计功能,这时候就需要使用annotate方法,annotate的中文是注释,因为统计结束后返回的依旧是一个查询集,统计的结果就如每个类的注释一样.

    举个例子,比如你想知道每个blog( 博客 )下面的comment( 评论 )个数:

>>> q = Blog.objects.annotate(Count('comment'))
>>> q[0].name
'Blog1'
>>> q[0].comment__count
50

    当然这里的comment后面的__count是默认值,如果你需要自定义这个值,只需要下面的操作即可:

>>> q = Blog.objects.annotate(number_of_comment = Count('comment'))
>>> q[0].number_of_comment
50

    order_by( *fields)

    排序功能,该方法默认返回一个查询集.你可以传入一个包含排序条件的列表进行排序.当然一个查询集会默认执行排序,如果你想修改,可以在Meta类中通过order_by更改ordering设置,例如:       

class Text:
    ....
    class Meta:
        ordering = text.objects.all().order_by('created')

    如果你想进行随机排序,可以直接传入'?'即可  如果你想知道这个查询集是否已经排序过,可以使用ordered属性来查看,该属性返回的是布尔值类型.

    还可以通过在两种方式改变降序和升序:

  •     在传入fields参数的时候,在参数前加-代表降序,不加代表升序.
  •     在fields的后面,再加上方法进行改变, **asc( )**代表升序 ,**desc( )**代表降序.

        

    切忌:

不要在一个order_by后又加一个order_by,后面的会覆盖掉之前的查询结果.

    reverse( )

使用reverse方法可以反转查询集的顺序.

text_blog.reverse()[:5]

    上面的语句显示的则是text_blog倒数5个

    注意:

reverse方法只适用于已经默认排序或者使用order_by排序过后的查询集,如果未排序,则没有效果.

    distinct( *fields)

    返回一个没有重复的查询集,可以通过参数修改需要避免重复.

    注意:

例如,其中entry是blog的外键,:

Entry.objects.order_by('blog').distinct('blog')

    这样会导致错误,因为查询集会按照blog__name进行排序,在blog的表中无发与'blog'进行匹配,所以出现错误.

    values(*fields, **expressions)

返回一个可以显示每个对象每个字段数值的查询集

# This list contains a Blog object.
>>> Blog.objects.filter(name__startswith='Beatles')
<QuerySet [<Blog: Beatles Blog>]>

# This list contains a dictionary.
>>> Blog.objects.filter(name__startswith='Beatles').values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>

    你可以给values方法传入需要显示的字段,那么输出的只有你需要的字段

>>> Blog.objects.values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
>>> Blog.objects.values('id', 'name')
<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>

    你也可以给values方法传入一个表达式

>>> from django.db.models.functions import Lower
>>> Blog.objects.values(lower_name=Lower('name'))
<QuerySet [{'lower_name': 'beatles blog'}]>

    values_list(*fields, flat=False, named=False)

values很相似,它返回的是迭代后的元祖,并且默认不显示字段名称,元祖中的数据顺序和参数相同

    如果只是需要数值组成的列表,可以给flat传入True,    

>>> Entry.objects.values_list('id').order_by('id')
<QuerySet[(1,), (2,), (3,), ...]>

>>> Entry.objects.values_list('id', flat=True).order_by('id')
<QuerySet [1, 2, 3, ...]>

同理,如果需要显示字段可以给named传入True

    dates(field, kind, order='ASC')

    field是需要查询输入的字段    kind可以是**"year""month""day"** order是排序

    该方法返回的是一个datetime.date对象的列表,根据kind进行区别,如果是year就以年来划分,以此类推

不返回查询集的方法

get(**kwargs)

    返回给定参数的查找对象.

    如果没有找到给定参数的对象则引发DoesNotExist异常

    如果找到了多个对象则引发MultipleObjectsReturned异常    

create(**kwargs)    

    创建对象并且直接保存入数据库

    

get_or_create(defaults=None,**kwargs)    

    这是上面两个方法的混合,如果存在则返回查找的对象,如果不存在则创建一个新的对象并且保存.

    

update_or_create(defaults= None,** kwargs)

    该方法查找defaults中的对象,如果找到则更新数值,如果没有,则创建对象.

    

count()

该方法返回与之匹配的数据库中对象的个数,并且有一个最大的特点,永远不会返回异常

in_bulk(id_list=None, field_name='pk')

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Karen110 Karen110
2年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
皕杰报表(关于日期时间时分秒显示不出来)
在使用皕杰报表设计器时,数据据里面是日期型,但当你web预览时候,发现有日期时间类型的数据时分秒显示不出来,只有年月日能显示出来,时分秒显示为0:00:00。1.可以使用tochar解决,数据集用selecttochar(flowdate,"yyyyMMddHH:mm:ss")fromtablename2.也可以把数据库日期类型date改成timestamp
Stella981 Stella981
2年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Wesley13 Wesley13
2年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这