QuerySetAPI笔记
学习Django时做的笔记MarkDown文件点这里
# 模型.objects:
这个对象是`django.db.models.manager.Manager`的对象,这个类是一个空壳类,他上面的所有方法都是从`QuerySet`这个类上面拷贝过来的。因此我们只要学会了`QuerySet`,这个`objects`也就知道该如何使用了。
`Manager`源码解析:
```python
class_name = "BaseManagerFromQuerySet"
class_dict = {
'_queryset_class': QuerySet
}
class_dict.update(cls._get_queryset_methods(QuerySet))
# type动态的时候创建类
# 第一个参数是用来指定创建的类的名字。创建的类名是:BaseManagerFromQuerySet
# 第二个参数是用来指定这个类的父类。
# 第三个参数是用来指定这个类的一些属性和方法
return type(class_name,(cls,),class_dict)
_get_queryset_methods:这个方法就是将QuerySet中的一些方法拷贝出来
```
## filter/exclude/annotate:过滤/排除满足条件的/给模型添加新的字段。
# order_by:
```python
# 根据创建的时间正序排序
articles = Article.objects.order_by("create_time")
# 根据创建的时间倒序排序
articles = Article.objects.order_by("-create_time")
# 根据作者的名字进行排序
articles = Article.objects.order_by("author__name")
# 首先根据创建的时间进行排序,如果时间相同,则根据作者的名字进行排序
articles = Article.objects.order_by("create_time",'author__name')
```
一定要注意的一点是,多个`order_by`,会把前面排序的规则给打乱,而使用后面的排序方式。比如以下代码:
```python
articles = Article.objects.order_by("create_time").order_by("author__name")
```
他会根据作者的名字进行排序,而不是使用文章的创建时间。
当然,也可以在模型定义的在`Meta`类中定义`ordering`来指定默认的排序方式。示例代码如下:
```python
class Meta:
db_table = 'book_order'
ordering = ['create_time','-price']
```
还可以根据`annotate`定义的字段进行排序。比如要实现图书的销量进行排序,那么示例代码如下:
```python
books = Book.objects.annotate(order_nums=Count("bookorder")).order_by("-order_nums")
for book in books:
print('%s/%s'%(book.name,book.order_nums))
```
# values :
用来指定在提取数据出来,需要提取哪些字段。默认情况下会把表中所有的字段全
部都提取出来,可以使用 'values' 来进行指定,并且使用了 'values' 方法后,提取出
的 QuerySet 中的数据类型不是模型,而是在 'values' 方法中指定的字段和值形成的字典:
```python
articles = Article.objects.values("title",'content')
for article in articles:
print(article)
```
以上打印出来的 'article' 是类似于 `{"title":"abc","content":"xxx"}` 的形式。
如果在 'values' 中没有传递任何参数,那么将会返回这个恶模型中所有的属性。
## 如果我们想要提取的是这个模型上关联的属性,那么也是可以的,查找顺序跟'filter'的用法是一样的,示例代码如下:
```python
books = Book.objects.valuse('id', 'name', author_name=("author__name"))
```
## 以上将会提取作者的名字字段,如果想要更改一个名字,可以使用关键字参数,示例代码如下:
```python
books = Book.objects.valuse('id', 'name', author_name=F("author__name"))
```
自定义的名字不能和已经存在的名字一样,比如`author_name`不能重复。
## 在`values`中可以使用聚合函数来形成一个新的字段,比如想要获取每本书的销量,示例代码如下:
```python
books = Book.objects.values('id', 'name', order_nums=Count("bookorder"))
```
# values_list
## 跟`values`是一样的作用,只不过这个方法返回的`QuerySet`中装的不是字典,而是元组,示例如下:
```python
books = Book.objects.values_list('id', 'name')
```
那么以上返回的结果是`(1,'三国演义')`,
## 如果给`values_list`只指定一个字段,那么可以指定`flat=True`,这样返回的结果就不是一个元组,而是这个字段的值,示例代码入下:
```python
books = Book.objects.values_list('name', flat=True)
```
## 注意`flat`只能用在只有一个字段的情况下,否则会报错
# all方法
## 返回一个`QuerySet`对象,没有做任何更改,会返回所有属性,很少用到。
# select_related方法
## 在提取某个模型的数据的同时,也提前将相关联的其他表的数据取出来,在以后访问相关联的的表的数据的时候,不用再次查找,节省开销。
比如提取文章数据的同时,可以取作者信息表的数据,示例代码如下:
```python
books = Book.objects.select_related("author","publisher")
for book in books:
print(book.author.name)
print(book.publisher.name)
# 因为在提取Book的时候,使用了select_related,那么以后在访问book.author 的时候,不会再次发起请求。
```
## 注意:这个方法只能用在外键的关联对象上,对于那种多对多、多对一的情况,不能使用此方法,而应该使用`prefetch_related`来实现。
# prefetch_related方法
## 和`select_related`方法类似,用在处理那种多对多、多对一的情况。
这个方法会产生两个查询语句,所以,如果在这个方法中查询使用外键关联的模型的时候,也会产生两个查询语句,因此,如果查询的是外键关联的模型,建议使用`select_related`方法。
在查询多对多关系或者一对多的关联的对象的时候,你在使用模型怎么访问这个多对多,那么久在这个方法中传递什么字符串,比如要获取图书的所有订单,示例代码如下:
```python
books = Book.objects.prefetch_related("bookorder_set")
```
## 注意:如果在使用`prefetch_related`查找出的`bookorder_set`,建议不要对他进行任何操作,比如`filter`,不然又会产生更多的查询语句,是不对的:
```python
books = Book.objects.prefetch_related("bookorder_set")
for book in books:
print('='*30)
print(book.name)
orders = book.bookorder_set.filter(price__gte=90)
for order in orders:
print(order.id)
```
## 如果确实想要对预先查找的集合进行操作,那么我们可以使用`models.Prefetch`来完成:
```python
# 先使用prefetch将查询的条件写好,再来使用。
prefetch = Prefetch("bookorder_set",queryset=BookOrder.objects.filter(price__gte=90))
books = Book.objects.prefetch_related(prefetch)
for book in books:
print('='*30)
print(book.name)
orders = book.bookorder_set.all()
for order in orders:
print(order.id)
```
# defer 方法
## 在一些表中,可能存在很多字段,但是一些字段的数据量可能是比较大的,而你此时又不需要,这个时候可以使用`defer`来过滤掉一些字段(可以是多个),这个字段跟`values`有点类似,只不过`defer`返回的不是字典,而是模型。
```python
books = Book.objects.defer("name")
```
## 注意: 使用`defer`的字段,以后再次使用的话,会再次发起请求,请谨慎操作。
# only
## 跟`defer`类似,不过`only`是只提取某些字段(可以是多个)。
```python
books = Book.objects.only('name')
# 默认是提取 'id'的
```
## 注意: 没有使用`only`的字段,以后想要使用的话,会再次发起请求,请谨慎操作。
# get 方法
## 获取满足条件的数据,这个函数只能返回一条数据,并且如果给的条件有多条数据,那么这个方法会抛出错误,如果给的条件没有任何数据,也会抛出错误,送一这个方法在获取数据的时候,只能有一条数据。
```pyhton
book = Book.objects.get(id=5)
```
# create 方法
## 创建一条数据,并且保存到数据库中,这个方法相当于先用指定的模型创建一个对象,然后再调用这个对象的`save`方法,示例如下:
```python
# publisher = Publisher(name='知了出版社')
# publisher.save()
publisher = Publisher.objects.create(name='知了课堂出版社')
```
# get_or_create 方法
## 根据某个条件进行查找,如果找到就返回这条数据,如果没有找到,那么就创建一个,示例代码如下:
```python
# result = Publisher.objects.get_or_create(name='知了abc出版社')
# print(result[0])
```
# bulk_create 方法
## 一次性创建多个数据,示例代码如下:
```
publisher = Publisher.objects.bulk_create([
Publisher(name='123出版社'),
Publisher(name='abc出版社'),
])
```
优势在于执行一次,将所有的数据都插入到数据库,效率高。
# count 方法
## 获取提取的数据的个数,如果想要知道总共有多少条数据,那么建议使用`count`,而不是`len(articles)`这种,因为`count`在底层使用`select count(*)`来实现,更加高效。
```python
count = Book.objects.count()
```
# first 和last 方法
## 返回`QuerySet`中的第一条和最后一条数据。
# aggregate 方法
## 使用聚合函数。
# exists 方法
## 判断某个条件的数据是否存在,如果要判断某个条件的元素是否存在,那么建议使用`exists`,这比直接使用`count`或者直接判读`QuerySet`更有效,实例代码如下:
```python
result = Book.objects.filter(name='三国演义').exists()
```
# distinct 方法
## 去掉那重复的数据,这个方法如果底层数据库用的是MySQL,那么不能传递任何值,比如想要提取所有销售的价格超过80元的图书,并且删掉那些重复的,那么可以使用`distinct`来实现,示例代码如下:
```python
order = BookOrder.objects.filter(bookorder__price__gte=80).distinct()
```
## 需要注意的是,如果`distinct`之前使用了`order_by`,那么因为`order_by`会提取`order_by`中指定的字段,因此再使用`distinct`就会根据多个字段来进行唯一化,所以就不会把那些重复的数据删掉。示例代码如下:
```python
order = BookOrder.objects.order_by('create_time').values('book_id').distinct()
```
那么以上代码因为使用了`order_by`,即使使用了`distinct`,也会把重复的`book_id`提取出来。
# update 方法
## 执行更新操作,在SQL底层走的也是`update`命令,比如将所有图书价格都怎加5,示例代码如下:
```python
Book.objects.update(price=F("price")+5)
```
# delete 方法
## 一次性可以把所有满足条件的数据都删除掉。
```python
Author.objects.filter(id__gte=3).delete()
```
## 注意:删除的时候注意数据表之间的关系(模板中`on_delete`指定的方式)。
# 切片操作
## 有时候我们查找数据,有可能只需要其中的一部分,那么这时候可以使用切片操作来帮助我们完成,`QuerySet`使用切片操作就跟列表使用切片操作是一样的,示例代码如下:
```python
books = Book.objects.all()[1:2]
```
切片操作并不是把所有数据从数据库中提取出来再进行切片操作,而是在数据库底层使用`limie`和`offset`来帮我们完成,所以如果只需要提取其中的一部分,建议使用切片操作。
# 什么时候`Django`会将`QuertSet`转化为SQL去执行:
生成一个`QuerySet`不会马上转化为SQL去执行。
1. 迭代:在遍历`QuerySet`对象的时候,会首先执行这个SQL语句,然后再把这个结果返回进行迭代,比如以下代码:
```python
for book in Book.objects.all():
print(book)
```
2. 使用步长进行切片操作:`QuerySet`可以类似于列表一样做切片操作,做切片操作本身不会执行SQL语句,但如果在做切片操作的时候提供了步长,那么就会立马执行SQL语句,需要注意的是,做切片后不能再执行`filter`方法,否则会报错。
3. 调用`len`函数:调用`len`函数来获取`QuerySet`中总共有多少条数据也会执行SQL语句
4. 调用`list`函数:调用`list`函数用来将一个`QuerySet`对象转化为`list`对象也会执行SQL语句
5. 判断:如果对某个`QuerySet`进行判断,也会执行SQL语句
QuerySetAPI笔记的更多相关文章
- Django笔记&教程 5-2 进阶查询——Queryset
Django 自学笔记兼学习教程第5章第2节--进阶查询--Queryset 点击查看教程总目录 Queryset相关内容其实蛮多的,本文只介绍一些常用的,详细的推荐查询官方文档:queryset-a ...
- git-简单流程(学习笔记)
这是阅读廖雪峰的官方网站的笔记,用于自己以后回看 1.进入项目文件夹 初始化一个Git仓库,使用git init命令. 添加文件到Git仓库,分两步: 第一步,使用命令git add <file ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- SQL Server技术内幕笔记合集
SQL Server技术内幕笔记合集 发这一篇文章主要是方便大家找到我的笔记入口,方便大家o(∩_∩)o Microsoft SQL Server 6.5 技术内幕 笔记http://www.cnbl ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- NET Core-学习笔记(三)
这里将要和大家分享的是学习总结第三篇:首先感慨一下这周跟随netcore官网学习是遇到的一些问题: a.官网的英文版教程使用的部分nuget包和我当时安装的最新包版本不一致,所以没法按照教材上给出的列 ...
- springMVC学习笔记--知识点总结1
以下是学习springmvc框架时的笔记整理: 结果跳转方式 1.设置ModelAndView,根据view的名称,和视图渲染器跳转到指定的页面. 比如jsp的视图渲染器是如下配置的: <!-- ...
- 读书笔记汇总 - SQL必知必会(第4版)
本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...
随机推荐
- 5.MySQL必知必会之过滤数据-WHERE
本章将讲授如何使用SELECT语句的WHERE子句指定搜索条件. 1.使用WHERE子句 数据库表一般包含大量的数据,很少需要检索表中所有行.通常只 会根据特定操作或报告的需要提取表数据的子集.只检索 ...
- SQLSERVER2016 无域控AlwaysOn 实施步骤
SQLSERVER2016 无域控AlwaysOn 实施步骤 步骤: 一.安装3个windows server 2016系统 1)在3台机器建立具有administrators权限的相同账号密码,本例 ...
- hdu4057 Rescue the Rabbit
地址:http://acm.hdu.edu.cn/showproblem.php?pid=4057 题目: Rescue the Rabbit Time Limit: 20000/10000 MS ( ...
- Java枚举类型定义方式
public enum Method { // get请求 GET("get"), // post请求 POST("post"); private String ...
- linux 注销其他用户
本文主要参考:http://ysz520020.blog.163.com/blog/static/352595722011969264745 linux kill掉其他的登录用户 : 方法一: 使用 ...
- C++MFC之picture control控件铺满图片
UpdateData(true); //更新路径公共变量 CString m_path = m_edit1.GetString(); if(m_path=="") ...
- Spark高级数据分析· 2数据分析
wget https://archive.ics.uci.edu/ml/machine-learning-databases/00210/donation.zip 数据清洗 cd /Users/eri ...
- Jquery8 基础事件
学习要点: 1.绑定事件 2.简写事件 3.复合事件 JavaScript 有一个非常重要的功能,就是事件驱动.当页面完全加载后,用户通过鼠标或键盘触发页面中绑定事件的元素即可触发.jQuery 为开 ...
- MySQL_解决ERROR 2006 (HY000) at line XX MySQL server has gone away问题
参考:http://www.111cn.net/database/mysql/106911.htm 1.修改mysqld的配置文件my.cnf 调整max_allowed_packet的值,修改为5M ...
- sbt安装与配置
下载地址:http://www.scala-sbt.org/download.html 当前版本:sbt-0.13.13.tgz 安装 1.解压并赋予权限 [root@hidden util]# ta ...