首页 > 其他分享 >Django笔记九之model查询filter、exclude、annotate、order_by

Django笔记九之model查询filter、exclude、annotate、order_by

时间:2023-04-19 23:35:42浏览次数:40  
标签:filter pub annotate objects exclude Entry 排序 order

本文首发于公众号:Hunter后端 原文链接:Django笔记九之model查询filter、exclude、annotate、order_by

在接下来四五篇笔记中,将介绍 model 查询方法的各个细节,为我们的查询操作提供各种便利。

本篇笔记将介绍惰性查找、filter、exclude、annotate等方法,目录如下:

  1. 惰性查找
  2. filter
  3. exclude
  4. annotate
  5. alias
  6. order_by

1、惰性查找

前面我们在介绍 Django 增删改查的时候,提到过他的惰性查找的规则。

也就是说普通的 filter 语句执行时,系统并不会去查询数据库,只有当我们真正使用里面的数据的时候,才会去查询数据库。

那么以下介绍几种,使用的时候会查询数据库的情况:

迭代

一个 QuerySet 是可迭代的,而且仅会在第一次迭代的时候查询数据库:

for e in Entry.objects.all():
	print(e.headline)

切片

需要注意的是,使用 python 里的切片语法不会访问数据库,比如:

Entry.objects.all()[:3]

但是,如果使用 step 语法则会访问数据库,比如以下语句:

Entry.objects.all()[:10:2]

len()

当我们使用 len() 函数去获取一个 QuerySet 的长度时,会访问数据库,比如:

len(Entry.objects.all())

但是这种做法是不被推荐的,因为他会把 QuerySet 中的所有数据,都加载出来,然后计算长度。

如果想要获取总数量,我们会使用另一个函数,.count(),这个我们后面会提到。

list()

这个操作会强制查询数据库,然后将一个 QuerySet 转换成 python 里的 list。

entry_list = list(Entry.objects.all())

在一般情况下,是不推荐的,因为相对于 list 而言,QuerySet 可以执行的函数更多。

bool()

判断是否存在数据:

if Entry.objects.filter(headline='hunter'):
	print('exists')

但是,在Django 里一般也不推荐,因为有更高效的用法,那就是使用 .exists() 函数,这个在后面会详细介绍。

2、filter()

filter 这个函数前面都有介绍,可以在其中添加符合筛选条件,也可以通过链式的形式来操作。

但是链式执行的用法是 and 逻辑,如果想要用 or 逻辑,可以使用 Q() 用法来连用,前面也简单介绍过。

3、exclude()

这个函数与 filter() 函数功能相反,是排除符合条件的数据。

4、annotate()

annotate 这个单词的意思是 注释,在 Django 里的用法是,通过对数据进行处理,比如一个表达式,或者是通过外键引入一个新的数据字段,或者是聚合出来一个结果(比如平均值,综合等),会在每一条返回的数据里面新增一个前面表达式的结果作为一个新的字段返回。

比如我们获取 Blog 这个 model 的时候,Entry 作为它的外键关系,我们可以获取关联了某条 Blog 的 Entry 的数量,并且作为新的字段添加到 Blog 里一起返回,其操作如下:

q = Blog.objects.annotate(number_of_entries=Count('entry'))
q[0].number_of_entries

5、alias()

alias() 的用法和 annotate 一样,都可以创建新的数据字段,但与 annotate() 不一样的是,其结果并不会作为一个字段返回,而是用于在使用的过程中做筛选,比如一个用法如下:

q = Blog.objects.alias(number_of_entries=Count('entry')).filter(number_of_entries__gt=1)

6、order_by()

对于 QuerySet 每次返回的结果,如果 Meta 里有 ordering 参数,使用见上一篇 Meta 的使用笔记,那么数据就会按照 ordering 的参数对数据进行排序后返回。

如果 Meta 里没有设置该参数,那么数据则会在有主键 id 的情况下按照 id 的顺序返回。

当然,我们也可以使用 order_by() 这个函数来对每一次搜索的数据进行排序的重写。

正序排序

比如我们想要对 Entry 这个 model 对于 pub_date 进行正序排序:

Entry.objects.filter(pub_date__year=2005).order_by('pub_date')

倒序排序

则可以在字段名前面加个 - 负号来操作:

Entry.objects.filter(pub_date__year=2005).order_by('-pub_date')

多个字段进行排序

比如 对 pub_date 倒序排序,对 headline 正序排序,则是:

Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')

按照外键字段排序

比如 Entry 这个 model 需要按照外键 Blog 的 name 字段来排序,则通过外键字段+双下划线+排序字段来实现:

Entry.objects.order_by('blog__name')

如果我们在查询 Entry 的时候直接根据外键字段,也就是 blog 来排序,Django 会使用 Blog,也就是外键的默认排序(即在 Blog 的 model 的 Meta 里设置的 ordering 来排序),如果外键没有定义默认排序,则会根据主键 id 来排序。

比如说,我们的 Blog model,如果没有在 Meta 里设置默认的 ordering,那么,下面的语句:

Entry.objects.order_by('blog')

则会等价于:

Entry.objects.order_by('blog_id')

如果在 Blog 的 model 的 Meta 里有设置 ordering=['name'],那么则等价于:

Entry.objects.order_by('blog__name')

查询表达式调用 asc() 或者 desc() 方法:

Entry.objects.order_by(Coalesce('summary', 'headline').desc())

asc() 和 desc() 有 nulls_first 和 nulls_last 来控制 null 如何被排序,是放在最开始还是最后面。

忽略大小写排序

我们可以通过对字段进行小写处理来达到忽略大小写排序的目的:

from django.db.models.functions import Lower
Entry.objects.order_by(Lower('headline').desc())

其中,Lower() 函数我们会在之后的介绍 Django 中使用数据库函数的时候详细讲解。

不排序

如果是不想对数据进行任何排序,则可以直接调用 order_by() 函数,不添加任何参数即可。

Entry.objects.order_by()

不支持链式处理

需要注意的是,不同于 filter() 函数的链式操作,order_by() 是不支持链式操作的,每添加一次 order_by(),前面的排序都会被后面的覆盖。

Entry.objects.order_by('headline').order_by('pub_date')

以上语句则仅会根据 pub_date 进行排序,headline 的排序则会被忽略。

这个功能如果要验证,很简答,只需要打印出上述语句转换成的 SQL 语句即可。

以上就是本篇笔记全部内容,接下来将要介绍的是 reverse、distinct、values、values_list 等用法。

标签:filter,pub,annotate,objects,exclude,Entry,排序,order
From: https://blog.51cto.com/u_16061969/6207549

相关文章

  • jsonfilter 和 jshn.sh
    jsonfilter和jshn.sh来源https://blog.csdn.net/weixin_39637151/article/details/110610608 OpenWRT下自带了两个处理JSON文件的工具。工具一:/usr/bin/jsonfilter运行/usr/bin/jsonfilter得到如下提示:/usr/bin/jsonfilter命令行参数-a:将输入当数组处理。-i:指......
  • SpringBoot利用Filter获取请求数据request和修改返回response中的数据
    WrapperedRequestimportjavax.servlet.ReadListener;importjavax.servlet.ServletInputStream;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletRequestWrapper;importjava.io.*;publicclassWrapperedRequestextendsHttpSe......
  • filter-policy、route-policy和ip-prefix默认处理方式
    1、route-policy    默认情况下是拒绝所有路由的,如果没有按照特定条件对路由进行匹配和允许,那么所有的路由都将被拒绝。因此,在配置route-policy时,需要明确地指定允许的路由条目。   也可以在最后加个空node,[Huawei]route-policynamepermit node102、ip-prefix......
  • asp.net mvc 之旅 —— 第六站 ActionFilter的应用及源码分析
       这篇文章我们开始看一下ActionFilter,从名字上其实就大概知道ActionFilter就是Action上的Filter,对吧,那么Action上的Filter大概有几个呢???这个问题其实还是蛮简单的,因为我们听说Mvc本身就是一个扩展性极强的框架,自然就是层层有拦截,层层有过滤,对吧,比如我们看到的如下Control......
  • How to use Linux shell command filter the IP address All In One
    HowtouseLinuxshellcommandfiltertheIPaddressAllInOne如何使用Linuxshell命令过滤IP地址questionHowtofilteroutthereallyusefulIPaddressfromlongstrings?如何从长字符串中过滤出真正有用的IP地址?$cat./dd-ip-notice-robot.sh$./dd......
  • AS_Path Filter的应用方式
    AS_PathFilter的应用方式AS_Path过滤器只定义一个过滤工具,需要在某个地方调用这个过滤工具才会最终生效。在BGP中可以有两种方式调用AS_Path过滤器:通过peer命令直接调用AS_Path_Filter。通过route-policy调用AS_Path_Filter。应用方式一:通过peer命令直接调用as-path-filter#ipas......
  • Python 利用正则表达式和filter函数 筛选序列(列表等)
    在 Python 中,序列类型包括字符串、列表、元组、集合和字典http://c.biancheng.net/view/4312.htmlPython内建的filter()函数用于过滤序列https://www.liaoxuefeng.com/wiki/1016959663602400/1017404530360000序列内逐个元素筛选filter并用list保存结果筛选的判断条件是re.match......
  • SpringSecurity过滤器-CsrfFilter
    CsrfFilter是为了防御CSRF攻击的。CSRF攻击请参考松哥手把手教你在SpringBoot中防御CSRF攻击!soeasy!。CsrfFilter的源码在要学就学透彻!SpringSecurity中CSRF防御源码解析说的很清楚了。 在这里是对LazyCsrfTokenRepository的使用做个总结。 CsrfFilter#doFilterI......
  • HDU 2473 Junk-Mail Filter(并查集的删除操作)
    题目地址:HDU2473这题以前碰到过,没做出来。。现在又做了做,还是没做出来。。、、这题涉及到并查集的删除操作。想到了设一个虚节点,但是我把虚节点设为了要删除的点的父节点,一直是栈溢出,目测是无限递归了。看了看别人的做法,原来只要建一个映射就可以了,虚节点是作为的新的映射,每......
  • Rust中的迭代器的使用:map转换、filter过滤、fold聚合、chain链接
    什么是迭代器Rust中的迭代器是一种强大的工具,它提供了一种灵活、通用的方法来遍历序列。迭代器是实现了Iteratortrait的类型,并需要至少实现一个next函数,用于让迭代器指向下一个迭代对象,并返回一个Option用于指示对象是否存在。fnnext(&mutself)->Option<Self::Item>;迭......