QuerSets类的简单介绍
QuerySet是一个model 类对应的实例集合, 即数据库对应表的子集,可以称为查询集。
QuerySet可以构造,过滤,切片,通常情况下都不会对数据库造成修改。只有查找的时候才会真正地操作数据库
首先,QuerySet是可以迭代的对象,然后可以使用python的切片方法进行切片操作,返回的依旧是一个QuerySets的对象。
在一个QuerySet对象生成的时候,你可以使用len和list等函数对对象进行操作,计算出包含对象的长度和转化对象成为列表进行操作
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')