添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

QuerySet API

我们通常做查询操作的时候都是通过 "模型名字.objects" 的方式进行操作的。其实"模型名字.objects"是一个 "django.db.models.manager.Manager" 对象,而Manager这个类是一个"空壳"的类,它本身是没有任何的属性和方法的。它的方法全部都是通过Python以动态添加的方式,从QuerySet类中拷贝过来的(至于是如何拷贝的后面简单的介绍下,知道就好)

:本章的所有例子,大都基于这个模型类

例1:
⑴打印"模型名字.objects"

⑵查看"Manager"类
①通过步骤1的输出可以看到"模型名字.objects"返回的是一个"Manager"对象,因此查看"Manager"类
②导入"Manager"类:from django.db.models.manager import Manager
③选中"Manager"后Ctrl+B:查看源码

⑶查看"from_queryset"方法

注:
上面的源码什么的我是看得不是很懂的,只是想说明下: "objects"对象下面的方法都是从"QuerySet"对象下拷贝过来的,"QuerySet"对象对象下的方法,可以直接在"objects"对象下调用

返回新的QuerySet的方法

1、在使用QuerySet进行查找操作的时候,可以提供多种操作。比如过滤完后还要根据某个字段进行排序,那么这一系列的操作我们可以通过一个非常流畅的 "链式调用" 的方式进行。比如要从文章中获取标题为123,并且提取后要将结果根据发布时间进行排序,那么就可以通过下面的方式来完成: "article=Article.objects.filter(title='123').order_by('create_time')"

2、可以看到order_by方法是直接在filter()方法执行后调用的。这说明filter()方法返回的是一个拥有order_by方法的对象。而这个对象正是一个新的QuerySet对象,因此可以使用order_by方法(当然QuerySet对象还可以使用其他方法,这里只是以filter方法和order_by方法举例)

3、 只要返回的数据是一个QuerySet对象,那么就可以调用QuerySet对象方法(链式调用或分步调用) 。特别注意object对象中的方法是复制QuerySet对象下的方法的,因此object对象也可以直接调用QuerySet对象方法

4、本章介绍的都是QuerySet对象方法,因此这些方法都是可以组合使用的(除了有些QuerySet对象方法返回的不是QuerySet对象)

例1_1:

    info = User.objects.filter(create_time__gt="2020-10-14 21:58:48").filter(telephone=13355509333)
    print(info)
    #<QuerySet [<User: User object (8)>]>
    user = info = User.objects.filter(create_time__gt="2020-10-14 21:58:48")
    print(type(user))
    print(user.filter(telephone=13355509333))
    # <class 'django.db.models.query.QuerySet'>
    # <QuerySet [<User: User object (8)>]>

注:
1、上面例子中分别使用了两种写法来实现同一个查询

2、 filter()本来就是QuerySet对象下面的方法: 返回的是一个QuerySet对象,因此这个QuerySet对象又可以继续使用QuerySet对象下面的方法 (也就是这两章将要介绍的方法)
这里只是以两个filter()方法为例

3、一般采用的都是第一种写法,也就是"链式调用"

QuerySet对象方法

filter()

1、作用:将满足条件的数据提取出来,返回一个新的QuerySet对象

2、不论查询结果中有多少条数据都可以正常返回,无数据时也会返回一个空的QuerySet对象

例2:
⑴查看数据

⑵编辑视图:首次调用

注:
1、filter()方法是QuerySet对象下面的方法,那为什么objects对象也可以调用呢?Book.objects.filter(author_a_id__gte=1)
⑴这个就是我们前面介绍的:objects对象的方法等都是拷贝(继承)于QuerySet对象的,因此objects对象可以直接调用QuerySet对象下面的方法了

2、从上面的输出结果可以看到:QuerySet对象下的方法filter(这里以filter方法为例),返回的是一个新的QuerySet对象,因此在返回结果上又可以继续使用QuerySet对象下的方法了

⑶编辑视图:继续调用

注:
上面例子中在过滤"id不等于3"时,不能写成"books = books.filter(id!=3)":如果这样写的话会报错'bool' object is not iterable
⑴在Python中"!="和"=="等返回的是一个bool类型的值,但是这种类型的值不能使用在Django的模型中
⑵因此在Django在过滤"不等"条件时,需要换种处理方式:先使用Q表达式找出"等于这个值"的值,然后在进行取反操作: books.filter(~Q(id=3))

⑷编辑视图:优化

例2_1:

⑴编辑模型

⑵查看数据

⑶编辑模板: 在模板使用变量来承接视图视图函数传递过来的值{ { img.url }}

⑷编辑视图

1、 使用filter()等方法来查找数据时,返回的是一个QuerySet对象,QuerySet对象是不能直接使用"QuerySet对象名.列名"来获取具体某列的值:需要先使用for循环来遍历得到每条数据的模型类,然后才能使用"模型类名.列名"来获取具体某列的值。这里的列名指的是模型类中对应列的属性名(模型类中的列名)

2、比如上面这个例子中就是在:模板类使用for标签来遍历视图函数传递过来的QuerySet对象,当然这个遍历也可以在视图函数中使用for循环来实现

get()方法

1、作用:获取满足条件的数据,直接返回的是一个模型且只有一条数据,因此可以直接使用 "模型名(实例名).属性名" 来获取具体列的值

2、这个函数只能返回一条数据,并且如果给的条件能查询出多条数据的话,这个方法就会抛出异常;如果给的条件没有查询出任何数据的话,也会抛出异常。因此 这个方法在获取数据的时候只能有且只有一条数据 (通常使用于主键id来进行查询)

all()

作用:获取这个ORM模型的QuerySet对象。因为 返回的是模型中的所有数据 (本身不会有过滤作用) ,并且所有的这些数据是简单的放在一个QuerySet对象的

例4:
⑴编辑视图

⑵编辑视图:用在子查询中

⑶编辑视图

注: 从上面例子可以看出
1、基于对象的查询(子查询)和基于双下划线的查询(join查询):在某些时候是可以达到同一目的的

values()

作用:用来提取指定的字段数据。默认情况下会把表中所有的字段全部提取出来,可以使用values()方法来指定只返回哪些字段,并且使用了values方法后,提取出的QuerySet对象中的数据模型不是模型,而是在valuses中指定的字段和值形成的字典

例5:
⑴编辑视图

注: 从上面例子可以看出
1、有时候我们在表中查询数据的时候,并不是想把所有的字段都提取出来。我们有可能只是想要查询其中的几个字段,这个时候就可以使用values()方法了

2、values()方法返回值同样也是一个QuerySet对象,但是这个QuerySet对象中装的就不再是模型了,而是查询出来的数据组成的字典了

3、values()方法的作用只是返回指定字段的值,其并没有过滤作用,因此values()方法更多的是和filter()等方法一起使用的

例5_1:
⑴编辑视图:join正向查询

⑵编辑视图:join反向查询

⑶编辑视图

⑷编辑视图

⑸编辑视图:结合聚合函数

注:
1、在进行关联字段查询时,如果想更改一下返回结果中的键名时,可以使用关键字参数(加F表达式)来指定返回数据的键名

2、不过,自定义的名字不能和模型上本身拥有的字段名字一样,不然会报错

3、如果调用values()方法时,没有传递任何参数,那么会获取这个模型上的所有字段以及对应的值形成的字典

values_list()

作用:类似于values()方法,只不过返回的QuerySet对象中存储的不是字典而是元组

例6:
⑴编辑视图

⑵编辑视图

注:
1、values_list()方法如果只返回一个字段,那么可以给其添加一个flat=True的参数:返回结果就不在是一个元组了,而知这个字段的值

2、flat=True参数只能在只返回一个字段时使用,如果返回的字段数大于1,那么就会报错

3、values()方法和values_list()方法的作用只是返回指定字段的值,并没有过滤作用,因此两个方法更多的是和filter()等方法一起使用的(先通过其他方法过滤查询出数据,然后选择是否使用values()方法和values_list()方法来获取指定字段的值)

exclude()

作用:排除满足条件的数据,返回一个新的QuerySet对象

annotate()

作用:给QuerySet中的每个对象都添加一个使用查询表达式(可以是聚合函数、F表达式、Q表达式、Func表达式)的新字段

例8: 查询每一本书的作者
⑴编辑视图:常规操作

⑵编辑视图

order_by()

作用:指定将查询的结果根据某个字段进行排序。如果要倒叙排序,那么可以在这个字段的前面加一个负号

例9:
⑴编辑视图

⑵增加模型类

⑶查看数据

⑷编辑视图

⑸模型类的ordering属性

select_related()

1、作用:在提取某个模型的数据的同时,也提前将相关联的数据提取出来

2、比如:提取文章数据时,可以使用select_related()方法将Author模型类中的数据提取出来,以后再使用article.author的时候就不需要再次去访问数据库了,可以减少数据库查询的次数

3、单独使用select_related()方法时是获取的全部数据,因此可以先使用filter()等方法过滤出数据后,再使用select_related()方法(这篇将的都是QuerySet对象的方法,因此只要是一个QuerySet对象,那么这篇文章中的所有方法基本上都可以混合使用)

4、select_related()只能从子表开始通过外键字段名来获取主表中的数据(7一对多关系中),但是不能通过主表开始获取子表中的数据
⑴这个方法只能用在外键的关联对象上,对于那种多对多的情况,不能使用这个方法来实现,而应该通过"prefetch_related"来实现

例10:
⑴编辑视图:常规方法

⑵编辑视图

⑶编辑视图

注:
1、使用常规方法时:每次在执行"book.author_a.name"时,即每次通过图书去查询作者时,都会去Author模型类中进行一次查询,这样的话就会耗性能,特别是有很多数据时

2、使用select_related()方法时,在查询Book模型类数据时,通过其方法中的参数就可以一次性的将关联表中的数据查询出来,后面就直接是获取Author中的数据了而不再需要再次查询

3、使用for循环来遍历QuerySet对象,然后依次返回每个数据的模型类,进而可以使用"模型类.字段名"来获取具体某个字段的值

4、只有返回数据为一个模型时,才能使用"模型类.字段名"来获取具体某个字段的值

5、注意:这个例子中是从子表到主表且表关系为一对多,因此主表中只会有一条数据,因此可以直接使用"模型类.字段名"来获取主表中具体某列的值
⑴如果是从主表到子表且表关系为一对多,因此子表中可能有多条或一条,如果子表数据为多条时,那么就需要先使用all()方法获取全部数据(此时为QuerySet对象),然后使用for循环遍历,然后才能使用"模型类.字段名"来获取子表中具体某列的值

prefetch_related()

1、作用:这个方法和select_related()方法类似,就是在访问多个表中的数据的时候,减少查询的次数

2、这个方法时为了解决多对一和多对多的关系的查询问题。例如要获取一个作者下的所有文章(一对多关系中:从主表到子表)

例11:
⑴编辑视图

⑵编辑视图

注:
使用 "模型类名.列名"来获取某一个列具体的值时:
⑴前提是返回的是一个模型类,而不是一个QuerySet对象。如果是一个QuerySet对象,那么就需要通过for循环遍历来依次返回每个具体数据的模型类
⑵只有返回的数据是一条数据的模型类时,才能使用"模型类.字段名"来获取某一个列具体的值:如一对多中,子表到主表,主表肯定只有一条数据,那么就可以直接使用"模型类.字段名"来获取某一个列具体的值
⑶如果返回的是多条数据的模型类,那么就必须先使用for循环来遍历依次得到每条数据的模型类,然后才能使用"模型类.字段名"来获取某一个列具体的值:如一对多中,主表到子表,子表数据可以有一条或多条,当为多条时先使用all()来获取全部数据,然后遍历,再使用"模型类.字段名"
其实不管使用什么方法,只要返回的是多条数据,那么都需要使用for循环来依次遍历出每条数据,然后才能使用"模型类名.列名"来获取某一个列具体的值。如果是对多条数据使用"模型类名.列名"的话肯定是不行的,都不知道获取的是哪条数据中的例值

defer()

1、作用:在一些表中,可能存在很多字段,但是一些字段的数据量可能是比较大的,而此时你又不需要。比如在获取文章列表的时候,文章的内容不是我们所需要的,因此这时候我们就可以使用defer()方法来过滤掉一些字段

2、defer()方法的作用与value()方法有点类似,只不过defer()方法返回的不是字典,而是模型

例12:
⑴编辑视图:可以传入多个字段

注:
1、从上面的SQL语句可以看到,查询文章的字段时,除了price,其他字段都查找出来了。当然,也可以使用book.price来获取这个文章的价格,但是会重新执行一个查询语句

2、defer()方法虽然能过滤字段,但是有些字段是不能过滤的,比如id列,即使你过滤了,也会提取出来

only()

作用:跟dfer()方法类似,只不过defer()方法是过滤指定的字段,而only是只提取指定的字段

例13:
⑴编辑视图:可以传入多个字段

QuerySet对象特性

1、QuerySet对象是可迭代的、可切片的。在一定程度上感觉QuerySet对象具有很多序列的特性

2、另外,还可以对QuerySet对象集使用 random.choice() 方法:随机选择一个QuerySet对象

1、对一个QuerySet对象进行遍历其实已经使用过很多次了

2、QuerySet对象不仅可以在视图函数中进行遍历,也可以在模板中进行遍历

例14: 在视图函数中进行遍历
⑴编辑视图

⑵编辑模板


例15: 在模板中进行遍历
⑴编辑视图

⑵编辑模板

注:
1、可以看到如果需要传递模板并且传递数据的话,那么在模板中就行遍历会简便得很多
⑴在视图函数中遍历再整理成其他数据类型会显得很是多余

1、对QuerySet对象进行切片,其操作方式与Python中对序列进行切片是一样的

2、依旧使用 "[start:end:step]" 来进行

3、注:虽然QuerySet对象可以进行切片,但是QuerySet对象不能进行索引

例16:
⑴编辑视图

QuerySet对象转为json序列

1、将QuerySet对象转为json序列,通常有几种方式
⑴第一种就是完全使用Python方法,例如前面例14种一样:
①先遍历依次得到每个QuerySet对象的值,使用dict(zip())方法,打包为字典,然后使用json.dumps()方法转为json序列
⑵利用django的model_to_dict将queryset序列化成字典(注意是字典)
利用Django的serialize序列化成json对象

例17: 利用django的model_to_dict将queryset序列化成字典
⑴编辑视图


例18: 利用Django的serialize序列化成json对象(django自带的序列化器)
⑴编辑视图

注:
1、如果我们视图函数需要返回的是一个JsonResponse对象的话,使用这个方法来将QuerySet对象转为json数据就非常方便了,就不需要我们手动去构建这个josn数据
⑴导入所需模块:from django.core.serializers import serialize
⑵调用 serialize(format, queryset, **options) 方法

2、serialize()方法至少接收两个参数
⑴第一个是你要序列化成为的数据格式,这里是"json",还可以是python、xml等
⑵第二个是要序列化的数据对象,数据通常是ORM模型的QuerySet,一个可迭代的对象

3、另外关于序列化QuerySet对象的方法,感觉有一篇文章写得很详细:https://www.liujiangblog.com/course/django/171

4、 rest_framework框架 简介它是基于Django的,帮助我们快速开发符合restful规范的接口框架,它主要适用于前后端分离项目
⑴如果使用这个框架的话,就能很方便的返回json数据

例19: 使用QuerySet对象下value()方法返回指定字段数据
⑴编辑视图

注:
1、Django序列化程序只能序列化查询集
⑴values()不返回queryset集而是返回ValuesQuerySet对象
⑵所以,需要避免使用values()后进行序列化
⑶而是需要在serialize方法中指定需要返回的字段

例20:
⑴编辑视图

QuerySet API我们通常做查询操作的时候都是通过"模型名字.objects"的方式进行操作的。其实"模型名字.objects"是一个"django.db.models.manager.Manager"对象,而Manager这个类是一个"空壳"的类,它本身是没有任何的属性和方法的。它的方法全部都是通过Python以动态添加的方式,从QuerySet类中拷贝过来的(至于是如何拷贝的后面简单的介绍下,知道就好)注:本章的所有例子,大都基于这个模型类例1:⑴打印"模型名字.ob.. 试试 FAQ —— 这里有很多常见问题的解答。 正在寻找特定的信息?试试 索引,模块索引 或者 详细内容目录。 在 django -users 邮件列表的档案库搜索,或者 post a question。 在 # django IRC channel 频道提问 在我们的 ticket tracker 报告关于 Django 的 Bug。 这份文档是如何组织的 Django 有丰富的文档。一份高度概述的文档会告诉你在哪里找到特定的东西: 教程 通过手把手地方式教你一步步的创建一个 Web 应用。如果你初学 Django 或编程,请从这里开始。也请看看下面的 "快速入门"。 专题指南 在相当高的层次上介绍关键主题和概念,并提供有用的背景信息和解释。 参考指南 包含 API 和 Django 各个工作机制方面的技术参考。它们介绍了 Django 是如何工作,如何被使用的。不过,你得先对关键字的概念有一定理解。 操作指南 是一份目录。它们以排列好的关键问题和用例的方式指导你。它们比教程更加深入,且需要你先了解一些关于 Django 是如何工作的知识。 您是刚学 Django 或是初学编程? 这就是你开始学习的地方! 从零开始: 概要 | 安装 入门教程: 第1节: 请求和响应 | 第2节: 模型 和 admin 站点 | 第3节: 视图和模板 | 第4节: 表单和通用视图 | 第5节: 测试 | 第6节: 静态文件 | 第7节: 自定义 admin 站点 进阶教程 : 如何编写可复用的应用 | 提交你的第一个 Django 补丁 Django 提供了一个抽象的 模型 ("models") 层,为了构建和操纵你的Web应用的数据。阅读下面内容了解更多: 模型 : 模型 介绍 | 字段类型 | 索引 | Meta 选项 | Model 类 Query Set : 执行查询 | Query Set 方法参考 | 查询表达式 Model 实例: 实例方法 | 访问关联的 对象 迁移: 迁移概述 | 操作参考 | SchemaEditor | 编写迁移 高级: 管理员 | 原始 SQL | 事务 | 聚合 | 搜索 | 自定义字段 | 多个数据库 | 自定义查询 | 查询表达式 | 条件表达式 | 数据库函数 其它: 支持的数据库 | 旧数据库 | 提供初始化数据 | 优化数据库访问 | PostgreSQL 的特定功能 Django 具有 “视图” 的概念,负责处理用户的请求并返回响应。通过以下链接查找所有你需要知道的有关视图的信息: 基础: URL配置 | 视图函数 | 便捷工具 | 装饰器 参考: 内置视图 | Request/response 对象 | TemplateResponse 对象 文件上传: 概览 | 文件 对象 | 存储 API | 管理文件 | 自定义存储 基于类的视图: 概览 | 内置显示视图 | 内置编辑视图 | 使用混入 | API 参考 | 扁平化索引 高级: 生成 CSV | 生成 PDF 中间件: 概览 | 内建的中间件类 模板层提供了一个对设计者友好的语法用于渲染向用户呈现的信息。学习如何使用语法(面向设计者)以及如何扩展(面向程序员): 基础: 概述 对于设计者: 语法概述 | 内建标签及过滤器(filters) | 人性化 针对程序员: 模板 API | 自定义标签(tags)和过滤器(filters) Django 提供了一个丰富的框架来帮助创建表单和处理表单数据。 基础: 概览 | 表单 API | 内建字段 | 内建 widgets 进阶: 针对 模型 的表单 | 整合媒体 | 表单集 | 自定义验证 学习众多的组件及工具,来帮助你开发和测试 Django 应用: 设置: 概览 | 完整的设置列表 应用程序: 概览 异常: 概览 django -admin.py 和 manage.py: 概览 | 添加自定义命令 测试: 介绍 | 书写并运行测试 | 包含的测试工具 | 高级主题 部署: 概览 | WSGI 服务器 | 部署静态文件 | 用 email 跟踪代码错误 找到所有你想知道的,关于自动化管理界面的知识, Django 最受欢迎的特性之一: 管理文档生成器 在 Web 应用的发展中,安全是最重要主题, Django 提供了多种保护手段和机制。 在 Django 中披露的安全问题 点击劫持保护 在语句Book.objects.all()中, objects 是一个特殊的属性,通过它来查询数据库,它就是 模型 的一个Manager. 每个 Django 模型 至少有一个manager,你可以创建自定义manager以定制数据库的访问. 这里有两个方法创建自定义manager:添加额外的manager;修改manager返回的初始 Query set . 添加额外的manager 增加额外的manager是为模块添加 表级功能 的首选办法.(至于 行级功能 ,也就是只作用于 模型 实例 对象 的函数,则通过自定义 模型 方法实现). 例如,为Book 模型 添加一个 title_
Django Query Set s酷毙了! 在本文中我将解释一下 Query Set s是什么,它是如何工作的(如果你对它已经熟悉了,你可以直接跳到第二部分),我认为如果可以的话你应该总是返回 Query Set s 对象 ,下面让我来谈谈如何做。 Query Set s很酷 Query Set ,本质上是一个给定的 模型 对象 列表。我说“列表”而不是“组”或更正式的“集合”因为它是有序的。事实上,你可能已经熟悉如何获得 Query Set s,因为这就是你调用variousBook.objects.XXX()方法后得到的 对象 。例如,考虑下面的语句: Book.objects.all() all()返回的就是Book
在查询时发生了什么(When Query Set s are evaluated) Query Set 可以被构造,过滤,切片,做为参数传递,这些行为都不会对数据库进行操作。只要你查询的时候才真正的操作数据库。 下面的 Query Set 行为会导致执行查询的操作: 循环(Iteration): Query Set 是可迭代的,在你遍历 对象 时就会执行数据库操作。例如,打印出所有博文的大标题: fo...
一、 Query Set 何时被提交 在内部,创建、过滤、切片和传递一个 Query Set 不会真实操作数据库,在你对查询集提交之前,不会发生任何实际的数据库操作。可以使用下列方法对 Query Set 提交查询操作: 迭代: Query Set 是可迭代的,在首次迭代查询集时执行实际的数据库查询。 例如, 下面的语句会将数据库中所有Ent... skus: Unable to get repr for <class ' django .db.models. query . Query Set '> 检查了下MySQL数据库是有数据的,代码也是正确的,网络也正常。 解决思路: 根据错误提示, 模型 类没有响应,那么就是数据
该项目现在需要Python 3.7+和 Django 3.0+。 对于以前的版本,请参考相关的标签或分支。 用于 Django 的Elasticsearch 这是一个轻量级的 Django 应用程序,适用于将Elasticsearch与 Django 结合使用并希望管理其索引的人们。 注意,master分支现在基于ElasticSearch7。如果您使用的是旧版本,请切换到相关分支(在PyPI上以2.x,5.x,6.x发行) 搜索索引生命周期 搜索索引的基本生命周期很简单: 创建一个索引 将文件过帐到索引 将其与我们在 Django 项目中使用搜索相关联,如下所示: 为命名索引创建映射文件 将索引配置添加到 Django 设置 将 模型 映射到索引中的文档类型 将 对象 的文档表示形式发布到索引 更新 对象 时更新索引 删除 对象 后删除文档 将搜索结果转换为 Query Set (保留相关性) 网上也有类似方法,只是搜索结果多少有些问题,总是搜了好一会儿才找到最简便的方法,但是只是简单些的 对象 ,对于复杂的 对象 ,还是不容易找到好的方式。 方案(python3.6): 对象 转json: model类 class People(): def __init__(self, name, age,...
class Person(models.Model): p_name = models.CharField(max_length=18, unique=True) p_age = models.IntegerField(default=18, db_column='age') # False表示男,True表示女 p_sex = models.BooleanField(default=Fa..
这个错误提示是因为 Django 在数据库中找不到名为 django _session 的表。这个表是用来存储用户会话信息的,如果没有创建这个表, Django 就会报出这个错误。 解决方法是运行 Django 的数据库迁移命令,让 Django 自动创建这个表。具体操作步骤如下: 1. 在项目根目录下运行命令行工具,输入以下命令创建迁移文件: python manage.py makemigrations 2. 运行以下命令执行数据库迁移: python manage.py migrate 这样就可以创建 django _session 表了,再次运行程序就不会出现这个错误了。