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 表了,再次运行程序就不会出现这个错误了。