学习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笔记的更多相关文章

  1. Django笔记&教程 5-2 进阶查询——Queryset

    Django 自学笔记兼学习教程第5章第2节--进阶查询--Queryset 点击查看教程总目录 Queryset相关内容其实蛮多的,本文只介绍一些常用的,详细的推荐查询官方文档:queryset-a ...

  2. git-简单流程(学习笔记)

    这是阅读廖雪峰的官方网站的笔记,用于自己以后回看 1.进入项目文件夹 初始化一个Git仓库,使用git init命令. 添加文件到Git仓库,分两步: 第一步,使用命令git add <file ...

  3. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  4. SQL Server技术内幕笔记合集

    SQL Server技术内幕笔记合集 发这一篇文章主要是方便大家找到我的笔记入口,方便大家o(∩_∩)o Microsoft SQL Server 6.5 技术内幕 笔记http://www.cnbl ...

  5. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  6. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  7. NET Core-学习笔记(三)

    这里将要和大家分享的是学习总结第三篇:首先感慨一下这周跟随netcore官网学习是遇到的一些问题: a.官网的英文版教程使用的部分nuget包和我当时安装的最新包版本不一致,所以没法按照教材上给出的列 ...

  8. springMVC学习笔记--知识点总结1

    以下是学习springmvc框架时的笔记整理: 结果跳转方式 1.设置ModelAndView,根据view的名称,和视图渲染器跳转到指定的页面. 比如jsp的视图渲染器是如下配置的: <!-- ...

  9. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

随机推荐

  1. 微信小程序组件switch

    表单组件switch:官方文档 Demo Code: Page({ switch1Change: function (e){ console.log('switch1 发生 change 事件,携带值 ...

  2. 技术分享会(二):SQLSERVER索引介绍

    SQLSERVER索引介绍 一.SQLSERVER索引类型? 1.聚集索引: 2.非聚集索引: 3.包含索引: 4.列存储索引: 5.无索引(堆表): 二.如何创建索引? 索引示例: 建表 creat ...

  3. PKU 2352 Stars(裸一维树状数组)

    题目大意:原题链接 就是求每个小星星左小角的星星的个数.坐标按照Y升序,Y相同X升序的顺序给出由于y轴已经排好序,可以按照x坐标建立一维树状数组 关键是要理解树状数组中的c[maxn]数组的构成方式, ...

  4. 中高级PHP开发者应该掌握哪些技术?

    中级PHP程序员 1.Linux 能够流畅的使用Shell脚本来完成很多自动化的工作:awk/sed/perl 也操作的不错,能够完成很多文本处理和数据统计等工作:基本能够安装大 部分非特殊的Linu ...

  5. maven 介绍(一)

    本文内容主要摘自:http://www.konghao.org/index 内部视频                              http://www.ibm.com/developer ...

  6. 优化netbeans启动速度

    NetBeans优化的目的是提高NetBeans的启动速度和运行速度.下面介绍的NetBeans优化技巧是在版本6.0beta2上的优化.经过实验,大大提高了NetBeans的启动速度. 1,修改英文 ...

  7. java并发再次积累

    监视器与锁之间的关系: 1.object monitor 是任何一个对象都有的内置的数据结构,它是用来协调使用当前对象的多个线程之间的执行顺序的(wait/notify),线程会block或者wait ...

  8. HBuilder android 打包指南(V客学院技术分享)

    前提:确保配置文件(manifest.json)已配置完,没有异常. 打包选项如下: Android 包名 :在Android系统中是判断一个App的唯一标识,不同的App可以有同样的名字,但是它的包 ...

  9. spring-boot单元测试

    一.为什么要写单元测试 很多程序员有两件事情不愿意做: 写注释. 写单元测试. 但是在看代码时又会希望有清晰明了的注释,重构代码时能有一套随时可以跑起来的单元测试. 最近在迁移一个项目,从sqlser ...

  10. goland 使用简单配置-不断更新

    1.格式化代码 Ctrl+Alt+L  格式化代码 2.快捷键可能被占用 用tools-file watchers file->setting->tools->file watche ...