Django 自学笔记兼学习教程第5章第2节——进阶查询——Queryset

点击查看教程总目录

Queryset相关内容其实蛮多的,本文只介绍一些常用的,详细的推荐查询官方文档:queryset-api

0 - 数据示例

为了方便本文后面内容举例,这里先展示下models.py和数据库表内容,

myapp/models.py在本章第一节,如下:

from django.db import models

class Person(models.Model):
gender = (
('male', '男'),
('female', '女'),
) name = models.CharField(max_length=60)
sex = models.CharField(max_length=32, choices=gender, default='男')
age = models.IntegerField()

数据库表Person如下

id name sex age
2 Li Hua male 20
3 Big Shuang male 24
4 Xiao Hong female 21
5 Xiao Hua female 19
6 Ellen female 20
7 Zhang Sirui female 22
8 Alex male 23
9 Zhao Wen female 24
10 Sun Wu male 18
11 Qian Kong male 22

可通过在Django下的交互式命令行,运行以下代码,快速生成数据库数据。

>>> from myapp.models import Person
>>> info_list = [
["Li Hua", "male", 20],
["Big Shuang", "male", 24],
["Xiao Hong", "female", 21],
["Xiao Hua", "female", 19],
["Ellen", "female", 20],
["Zhang Sirui", "female", 22],
["Alex", "male", 23],
["Zhao Wen", "female", 24],
["Sun Wu", "male", 18],
["Qian Kong", "male", 22],
]
>>> for info in info_list:
name, sex, age = info
pi = Person(name=name, sex=sex, age=age)
pi.save()

1 - 查询方法

filter

个人最常用的查询方法是filter,可以简单理解为按条件查找(筛选),该方法返回一个Queryset对象,

其语法为OneModel.objects.filter(**kwargs),其中OneModel为要查询的模型名,kwargs为查询条件,接受关键词(keyword)参数, 该关键字具体格式见本文第二部分。

使用举例如下(在Django下的交互式命令行里执行代码)

>>> from myapp.models import Person
>>> age_20 = Person.objects.filter(age=20)
>>> age_20
<QuerySet [<Person: Person object (2)>, <Person: Person object (6)>]>
>>> age_20[0]
<Person: Person object (2)>
>>> age_20[0].name
'Li Hua'

get

返回与给定查找参数唯一匹配的对象,

注意:如果查找条件能找到多个结果或者0个结果,该方法都会报错。

其语法为OneModel.objects.get(**kwargs)

使用举例如下(承接上文命令行中代码)

>>> lihua = Person.objects.get(name="Li Hua")
>>> lihua.name
'Li Hua'
>>> lihua.age
20

all

获取数据库表所有数据(严格来讲,这已经不算查询方法了)。

其语法为OneModel.objects.all()

示例如下

>>> persons = Person.objects.all()
>>> for p in persons: print(p.name, p.age, end=",")
>>> print()
Li Hua 20,Big Shuang 24,Xiao Hong 21,Xiao Hua 19,Ellen 20,Zhang Sirui 22,Alex 23,Zhao Wen 24,Sun Wu 18,Qian Kong 22,

raw

执行一个SQL查询,并返回一个django.db.models.query.RawQuerySet实例。

RawQuerySet实例可以像普通的QuerySet一样遍历以提供对象实例。

示例如下

>>> persons_above22 = Person.objects.raw("select * from myapp_person where age>22")
>>> for p in persons_above22: print(p.id, p.name, p.sex, p.age)
3 Big Shuang male 24
8 Alex male 23
9 Zhao Wen female 24

2 字段查找格式(Field lookups)

本文第一部分的filterget方法,都是接受**kwargs作为查询条件来搜索的。

这个又称为字段查找(Field lookups),效果为指定SQL WHERE子句内容。

第一部分只展示了最简单的查询条件:严格相等。

如果要查找一些其他的条件,比如说年龄大于20岁,名字里面含有a字母等等。

则需要使用某种方法标明这个条件,django里面通过字段查找类型(lookup type)实现了这种方法。

给字段field指定查找类型lookup的语法如下

field__lookup

不指定时默认查找类型为精确exact,

即以下两句效果等同

lihua = Person.objects.get(name="Li Hua")
lihua = Person.objects.get(name__exact="Li Hua")

对应的sql为

SELECT * from myapp_person WHERE name = 'Li Hua';

这里介绍一些常用的查找类型,更多请查阅官方文档:field-lookups

  • iexact: 忽略大小写
  • contains: 查询包含指定模式的字段,(区分大小写)。
  • icontains: 查询包含指定模式的字段,(忽略大小写)。

注:由于SQLite不支持区分大小写的LIKE操作符,所以SQLite中contains效果为icontains

  • in: 在给定的可迭代对象中,如列表、元组或查询集,还有字符串。
  • gt: 大于(记忆技巧:greater than首字母)。
  • gte: 大于或等于,(记忆技巧:greater than equal首字母)。
  • lt: 小于(记忆技巧:less than首字母)。
  • lte: 小于或等于,(记忆技巧:less than equal首字母)。
  • startswith: 开头匹配,(区分大小写)。
  • istartswith: 开头匹配,(忽略大小写)。
  • endswith: 结尾匹配,(区分大小写)。
  • iendswith: 结尾匹配,(忽略大小写)。
  • regex: 正则匹配,(区分大小写)。
  • iregex: 正则匹配,(忽略大小写)。

注: 正则表达式语法是Python的re模块的语法。

举例演示:

>>> name_a = Person.objects.filter(name__icontains="a")
>>> for p in name_a: print(p.name, end=", ")
>>> print()
Li Hua, Big Shuang, Xiao Hong, Xiao Hua, Zhang Sirui, Alex, Zhao Wen, Qian Kong,
>>> age_lte_20 = Person.objects.filter(age__lte=20)
>>> for p in age_lte_20: print(p.name, p.age, end=", ")
>>> print()
Li Hua 20, Xiao Hua 19, Ellen 20, Sun Wu 18,

注:由于查找类型语法,是通过在字段名后面加两个下划线后声明的。

所以Django的模型中的属性字段名不可有两个下划线。

3 quertset 基础操作

使用filterall方法获取到的都是一个queryset对象,

所以我们也需要掌握该对象一些常用的方法和操作。

首先,queryset对象是一个可迭代对象,

这意味着它可以使用for循环遍历。

同时queryset对象也可以使用切片操作。

还可以使用lenlist等函数获取其对应结果。

queryset对象常用方法:

  • order_by: 按指定字段排序,可指定多个字段(从前往后按字段来排序)。

    默认升序,在字段名前加负号则降序。

使用示例:

>>> persons = Person.objects.all()
>>> persons_sorted_age = persons.order_by("age")
>>> for p in persons_sorted_age: print(p.name, p.age, end=", ")
>>> print()
Sun Wu 18, Xiao Hua 19, Li Hua 20, Ellen 20, Xiao Hong 21, Zhang Sirui 22, Qian Kong 22, Alex 23, Big Shuang 24, Zhao Wen 24,
>>> persons_sorted_age_descending = persons.order_by("-age")
>>> for p in persons_sorted_age_descending: print(p.name, p.age, end=", ")
>>> print()
Big Shuang 24, Zhao Wen 24, Alex 23, Zhang Sirui 22, Qian Kong 22, Xiao Hong 21, Li Hua 20, Ellen 20, Xiao Hua 19, Sun Wu 18,
  • order_by: 按指定字段排序,可指定多个字段(从前往后按字段来排序)。

    默认升序,在字段名前加负号则降序。

4 操作符

本文第二部分介绍了字段查找的基础格式。

且查询条件可以写多个,代表查找同时遵循这些条件的结果。

那么有一个问题,如果要查询满足A或B的结果,那么上面写法就不够用了。

Django实现了一个可以封装SQL表达式的对象Q,该对象在django.db.models中。

Q可以封装一个查询条件,

Q对象之间可以使用|(或)和&(且)符号,进行逻辑运算。

不仅可以实现上面指出的或查询问题,还可以可以定义和重用查询条件。

示例如下

>>> name_contains_a = Q(name__icontains="a")
>>> age_above_22 = Q(age__gt=22)
>>> and_res = Person.objects.filter(name_contains_a & age_above_22)
>>> for p in and_res: print(p.name, p.age, end=",")
>>> print()
Big Shuang 24,Alex 23,Zhao Wen 24,
>>> or_res = Person.objects.filter(name_contains_a | age_above_22)
>>> for p in or_res: print(p.name, p.age, end=",")
>>> print()
Li Hua 20,Big Shuang 24,Xiao Hong 21,Xiao Hua 19,Zhang Sirui 22,Alex 23,Zhao Wen 24,Qian Kong 22,

Django笔记&教程 5-2 进阶查询——Queryset的更多相关文章

  1. Django笔记&教程 6-4 forms进阶操作,重写forms方法

    Django 自学笔记兼学习教程第6章第4节--forms进阶操作,重写forms方法 点击查看教程总目录 1 - 重写clean方法 在本章第三节中,我们举了个注册学生账号的例子,里面我们使用模型来 ...

  2. Django笔记&教程 总目录

    本篇博客只有目录,正文内容在目录章节链接的博客里 除目录本身外,没有链接的章节,说明内容还没开始编辑 本项目笔记仍在不断创作中,还有些内容会根据自身所学不断更新完善 本项目主要为markdwon文档, ...

  3. Django笔记&教程 5-1 基础增删查改

    Django 自学笔记兼学习教程第5章第1节--基础增删查改 点击查看教程总目录 第四章介绍了模型类models.Model和创建模型,相当于介绍了数据库表和如何创建数据库表. 这一章将介绍如何使用模 ...

  4. Django笔记&教程 7-3 拓展CBVs(Class-based views)

    Django 自学笔记兼学习教程第7章第3节--拓展CBVs(Class-based views) 点击查看教程总目录 一般而言,直接使用原生的Class-based views,能展现的样式和内容是 ...

  5. Django笔记&教程 0-1 前言

    Django 自学笔记兼学习教程第0章第1节--前言 点击查看教程总目录 1 最初的想法 自学Django已经有一段时间了,自认收获不少,学的还算可以,然而实际去做项目写代码的时候,很多用法记得不清, ...

  6. Django笔记&教程 0-2 框架版本与相关工具

    Django 自学笔记兼学习教程第0章第2节-- 框架版本与相关工具 点击查看教程总目录 1 版本 python: 3.6.5 Django: 2.2.11 (有些地方我也会对比下各种版本的区别) 安 ...

  7. Django笔记&教程 1-1 一 新建项目

    Django 自学笔记兼学习教程第1章第1节--一 新建项目 点击查看教程总目录 1- 命令行新建Django项目 新建项目命令(project_name处为项目名) django-admin sta ...

  8. Django笔记&教程 1-2 二 常用配置

    Django 自学笔记兼学习教程第1章第2节--二 常用配置 点击查看教程总目录 新手建议简单浏览本文,不理解的建议跳过,不要强行理解. Django的设置涉及多个模块,需要了解Django的一些相关 ...

  9. Django笔记&教程 2-1 URL与View关系

    Django 自学笔记兼学习教程第2章第1节--URL与View关系 点击查看教程总目录 参考:how-django-processes-a-request 1- Django处理请求(request ...

随机推荐

  1. Appium+Python自动化环境搭建-1

    前言 appium可以说是做app最火的一个自动化框架,它的主要优势是支持android和ios,另外脚本语言也是支持java和Python. 小编擅长Python,所以接下来的教程是appium+p ...

  2. sonarqube C# 单元测试覆盖率一栏总是0%解决办法

    一.什么叫单元测试(unit testing)? 是指对软件中的最小可测试单元进行检查和验证.对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函 数,Java里 ...

  3. 四种引用类型在Springboot中的使用

    今天 4ye 来和小伙伴们聊聊这个 强引用,软引用,弱引用,幻象引用(虚引用)啦 嘿嘿,主要是最近读源码的时候经常看到,然后又想到自己第一次知道这个神奇的东西是在 2020-8-21 为啥记得这么清楚 ...

  4. Java面向对象编程(三)

    static关键词 static关键字:可以修饰属性.方法.代码块.内部类. 一.使用static修饰属性:静态变量(或类变量) 1. 属性,按是否使用static修饰,又分为:静态属性 vs 非静态 ...

  5. Spring动态代理的生成-如何判断是使用JDK动态代理还是CGlib代理

    前言 在上一篇文章中讲到了Spring是如何获取对应的Bean的增强,然后本次主要讲解一下Spring如何在获取到增强后创建Spring代理的. 在步入正题之前先给大家看一下Spring创建代理的大致 ...

  6. MySQL5.7主从复制-异步复制搭建

     两台服务器,系统是Redhat6.5,MySQL版本是5.7.18.1.在主库上,创建复制使用的用户,并授予replication slave权限.这里创建用户repl,可以从IP为10.10.10 ...

  7. iOS Swift结构体与类的方法调度

    前言 hello,小伙伴们:在忙碌中闲暇之余给大家聊聊swift的知识点,今天给大家带来的是swift中结构体与类的方法调度详细区别,希望对你有所帮助,好了废话不用多说,接下来步入主题! 1.普通方法 ...

  8. Java初步学习——2021.09.23每日报告,第三周周四

    (1)今天做了什么: (2)明天准备做什么? (3)遇到的问题,如何解决? 学习数组,编写了一个随机选牌的代码.自己最开始一直想只设置一个字符串数组,利用随机数来输出,但那样对字符串赋值会比较麻烦.可 ...

  9. 题解 [HAOI2012]道路

    题目传送门 题目大意 给出一个 \(n\) 个点 \(m\) 条边的有向图,问每一条边在多少个最短路径中出现. \(n\le 1500,m\le 5000\) 思路 算我孤陋寡闻了... 很显然,我们 ...

  10. 基本的bash shell命令

    目录 基本的bash shell命令 启动shell shell提示符 基本的bash shell命令 启动shell GNU bash shell 能提供对Linux系统的交互式访问.它是作为普通程 ...