浅谈Django QuerySet对象(模型.objects)的常用方法


Posted in Python onMarch 28, 2020

准备工作:

新建一个项目,在项目中新家一个app,名字自取。将app添加值settings.py中,然后配置settings连接数据库。

在app中的models中新建模型:

from django.db import models

# Create your models here.
class Author(models.Model):
  """作者模型"""
  name = models.CharField(max_length=100)
  age = models.IntegerField()
  email = models.EmailField()

  class Meta:
    db_table = 'author'


class Publisher(models.Model):
  """出版社模型"""
  name = models.CharField(max_length=300)

  class Meta:
    db_table = 'publisher'


class Book(models.Model):
  """图书模型"""
  name = models.CharField(max_length=300)
  pages = models.IntegerField()
  price = models.FloatField()  #书的定价
  rating = models.FloatField()
  author = models.ForeignKey(Author, on_delete=models.CASCADE)
  publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)

  class Meta:
    db_table = 'book'


class BookOrder(models.Model):
  """图书订单模型"""
  book = models.ForeignKey("Book", on_delete=models.CASCADE)
  price = models.FloatField()   #书卖出去的真正价格

  class Meta:
    db_table = 'book_order'

执行makemigrations后在migrate。

然后手动向表中添加数据,例如我添加的信息:

浅谈Django QuerySet对象(模型.objects)的常用方法

浅谈Django QuerySet对象(模型.objects)的常用方法

浅谈Django QuerySet对象(模型.objects)的常用方法

浅谈Django QuerySet对象(模型.objects)的常用方法

然后配置urls,直至项目运行成功。

1.filter:

过滤,将满足条件的数据提取出来,返回一个新的QuerySet。

2. exclude:

排除,排除满足条件的数据,返回一个新的QuerySet。

例如,取出book中id大于等于2的图书,并且id不能等于3的图书。示例代码:

books = models.Book.objects.filter(id__gt=1).exclude(id=3)

我们也可以使用Q表达式来实现,

from django.db.models import Q
books = models.Book.objects.filter(id__gt=1).filter(~Q(id=3))

3. annotate:

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

例如 给每本图书都添加一个字段叫author_name

from django.db.models import F
books = models.Book.objects.annotate(author_name = F('author__name'))

注意:

Book模型下面最开始是没有author_name这个属性的。只有一个author属性连接的一个外键.

author__name是book下的author属性下的name,即book这个表通过外键访问到author这个表中的name值。

执行完上述代码之后就在book中创建了一个新的属性author_name,但是只在内存中,不会映射到数据库中去。

4.order_by:

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

示例

def index2(request):
  # 1. 将book中的price属性按照从小到大进行排序
  # books = models.Book.objects.order_by('price')
  # for book in books:
  #   print("%s-%s"%(book.name,book.price))

  # 2. 将book中的price属性按照从大到小进行排序
  books = models.Book.objects.order_by('-price')
  for book in books:
    print("%s-%s"%(book.name,book.price))
  return HttpResponse('success')

修改对应注释代码哪呢个查看到效果。

需求:对价格进行排序,价格一样的就按照页数来进行排序,价格从小到大,页数从大到小。为了方便查看效果,可以先去数据库中修改数据。

def index2(request):
  # 1. 将book中的price属性按照从小到大进行排序
  # books = models.Book.objects.order_by('price')
  # for book in books:
  #   print("%s-%s"%(book.name,book.price))

  # 2. 将book中的price属性按照从大到小进行排序
  # books = models.Book.objects.order_by('-price')
  # for book in books:
  #   print("%s-%s"%(book.name,book.price))

  # 3. 对价格进行排序,价格一样的就按照页数来进行排序,价格从小到大,页数从大到小。
  books = models.Book.objects.order_by('price','-pages')
  for book in books:
    print("%s-%s-%s"%(book.name,book.price,book.pages))
  return HttpResponse('success')

注意:

books = models.Book.objects.order_by('price','-pages')不等于books = models.Book.objects.order_by('price').order_by('-pages')

如果使用多个order_by,会把前面排序的规则给打乱,只会使用最后面的一个排序方式。

order_by方法并没有改变数据库中的信息位置,只是我们将数据取出来进行了排序。

那么如果我们对数据库中的信息进行了排序,这样我们就不用每次取数据都需要进行一次排序了。应该怎样做呢?

我们只需要在模型中添加点代码就可以了。

例如:我们在Book者恶搞模型中对价格进行排序,价格一样的就按照页数来进行排序,价格从小到大,页数从大到小。

修改Book中的class Meta中的代码:

class Meta:
    db_table = 'book_order'
    ordering = ['price','-pages']

这样就对数据库中的信息进行了排序,我们在去数据 的时候也不用使用order_by来进行排序了。但是这样需要重新makegrations和migrate一下,这里就不做演示了。

需求:根据每本图书的销量来进行排序

from django.db.models import Q,F,Count

def index2(request):

# 1. 将book中的price属性按照从小到大进行排序
  # books = models.Book.objects.order_by('price')
  # for book in books:
  #   print("%s-%s"%(book.name,book.price))

  # 2. 将book中的price属性按照从大到小进行排序
  # books = models.Book.objects.order_by('-price')
  # for book in books:
  #   print("%s-%s"%(book.name,book.price))

  # 3. 对价格进行排序,价格一样的就按照页数来进行排序,价格从小到大,页数从大到小。
  # books = models.Book.objects.order_by('price','-pages')
  # for book in books:
  #   print("%s-%s-%s"%(book.name,book.price,book.pages))

  # 4. 根据每本图书的销量来进行排序
  results = models.Book.objects.annotate(sale_num=Count('bookorder__id')).order_by('sale_num')
  for result in results:
    print("%s-%s"%(result.name,result.sale_num))
  return HttpResponse('success')

因为Book这个模型中没有sale_num这个属性,所以我们需要使用annotate这个方法来创建一个sale_num属性,然后使用Count方法进行赋值,然后使用order_by 进行排序。就实现了这个需求。

5. values:

用来指定在提取数据出来,需要提取哪些字段。默认情况下会把表中所有的字段全部都提取出来,可以使用values来进行指定,并且使用了values方法后,提取出的QuerySet中的数据类型不是模型,而是在values方法中指定的字段和值形成的字典。

需求: 只需要提取Book中的id 和 name

示例:

def index3(request):

# 1. 只需要提取Book中的id 和 name
  books = models.Book.objects.values('id','name')
  for book in books:
    print(book)
  return HttpResponse('success')

注意: 返回的是一个字典类型。字典的key就是属性名,value是属性值。

需求:提取Book中的name和author__name,并且字典中的key自己指定,不使用默认的。字典的key分别为bookName和authorNmae

def index3(request):

# 1. 只需要提取Book中的id 和 name
  # books = models.Book.objects.values('id','name')
  # for book in books:
  #   print(book)

  # 需求:提取Book中的name和author__name,并且字典中的key自己指定,不使用默认的。
  # 字典的key分别为`bookName`和`authorNmae`
  books = models.Book.objects.values(bookName=F('name'),authorName=F('author__name'))
  for book in books:
    print(book)
  return HttpResponse('success')

注意:

自己取名字不能取该模型的属性名,否则会报错。

如果在value中不传递任何参数,那么会获取这个模型所有的值。返回的还是一个字典。

6:values_list:

类似于values。只不过返回的QuerySet中,存储的不是字典,而是元组。操作和values是一样的,只是返回类型不一样。

注意: 当我们使用此方法只返回一个值的时候,那么这个元祖中只有一个值,我们可以添加一个参数flat=True,将元祖去掉,从而得到一个字符窜。只有当values_list中只有一个值的时候才能使用这个方法:

示例:

books = models.Book.objects.values_list('name',flat=True)

7. all:

获取这个ORM模型的QuerySet对象。即获取所有的数据。

获取Book中所有数据

示例:

books = models.Book.objects.all()

8.select_related:

在提取某个模型的数据的同时,也提前将相关联的数据提取出来。比如提取文章数据,可以使用select_related将author信息提取出来,以后再次使用article.author的时候就不需要再次去访问数据库了。可以减少数据库查询的次数。

def index4(request):
  books = models.Book.objects.select_related('author')
  for book in books:
    print(book.author.name)
  return HttpResponse('succrss')

注意: select_related只能使用在设置了外键的模型中(即只能在一对多模型上,不能多对一,多对多等),比如我们只在Book设置了author外键和publisher外键。那么select_related里面只能传如这两个参数,而不能传入别的参数,如BookOrder,因为我们是在BookOrder中设置的外键连接到Book,并没有在Book中设置外键连接到BookOrder这个模型。

9. prefetch_related:

这个方法和select_related非常的类似,就是在访问多个表中的数据的时候,减少查询的次数。这个方法是为了解决多对一和多对多的关系的查询问题。

需求:从book中通过prefetch_related查询BookOrder中的信息。

示例代码

def index5(request):
  books = models.Book.objects.prefetch_related("bookorder_set")
  for book in books:
    print('*'*30)
    print(book.name)
    orders = book.bookorder_set.all()
    for order in orders:
      print(order.id)
  return HttpResponse('success')

prefetch_related方法也能办到select_related方法能办到的事情,只是select_related方法效率比prefetch_related方法效率高一点。所以能使用select_related方法的话就是用这个方法。但是这两种方法的执行效率都比传统的方法执行效率高。传统的方法就是先返回book对象,再通过book去查询对应的外键的相关信息。

10. defer:

在一些表中,可能存在很多的字段,但是一些字段的数据量可能是比较庞大的,而此时你又不需要,比如我们在获取文章列表的时候,文章的内容我们是不需要的,因此这时候我们就可以使用defer来过滤掉一些字段。这个字段跟values有点类似,只不过defer返回的不是字典,而是模型。

需求:过滤掉book 的name字段

def index6(request):
  # 过滤掉book的name字段
  books = models.Book.objects.defer('name')
  for book in books:
    print(book.id)

  return HttpResponse('sucdess')

注意: 我们在使用defer过滤掉name字段之后,我们还是可以访问到name属性,是因为当我们访问name属性的时候,Django又去执行了一遍sql语句查询的代码。所以在我们开发的过程中,除非我们确定不会使用到此属性,否则不要去过滤它。

defer虽然能过滤字段,但是有些字段是不能过滤的,比如id,即使你过滤了,也会提取出来。

11. only:

跟defer类似,只不过defer是过滤掉指定的字段,而only是只提取指定的字段。

需求:只提取name属性

# 只提取name属性
  books = models.Book.objects.only('name')
  for book in books:
    print(book.id,book.name)

注意: id这个字段我们是不能操作的,像上面一样,我们没有提取id属性,但是还是给我们提取出来了。所以id属性是一定会被提取出来的。

和defer一样,就算我们没有提取某个属性出来,我们还是可以访问到的,只是会重新执行一遍sql代码而已。

12. get:

获取满足条件的数据。这个函数只能返回一条数据,并且如果给的条件有多条数据,那么这个方法会抛出MultipleObjectsReturned错误,如果给的条件没有任何数据,那么就会抛出DoesNotExit错误。所以这个方法在获取数据的只能,只能有且只有一条。

# 获取id为1的数据
book = models.Book.objects.get(id=1)

13. create:

创建一条数据,并且保存到数据库中。这个方法相当于先用指定的模型创建一个对象,然后再调用这个对象的save方法。

publusher = models.Publisher.objects.create(name='知了出版社')

14. get_or_create:

根据某个条件进行查找,如果找到了那么就返回这条数据,如果没有查找到,那么就创建一个。

result = models.Publisher.objects.get_or_create(name='知了出版社')
print(result)

会返回一个元祖

查找的对象以及是否创建了这条数据。False就是没有创建这条数据。

15. bulk_create:

和create方法类似,只是这个方法可以一次性创建多个数据。

publusher = models.Publisher.objects.bulk_create([models.Publisher(name='123出版社'),
models.Publisher(name='abc出版社'),])

16. count:

获取提取的数据的个数。如果想要知道总共有多少条数据,那么建议使用count,而不是使用len(articles)这种。因为count在底层是使用select count(*)来实现的,这种方式比使用len函数更加的高效。

count = models.Book.objects.filter(name='xxx').count()

17. first和last:

返回QuerySet中的第一条和最后一条数据。如果为空则返回none。

18. aggregate:

使用聚合函数。

19. exists:

判断某个条件的数据是否存在。如果要判断某个条件的元素是否存在,那么建议使用exists,这比使用count或者直接判断QuerySet更有效得多。

示例代码如下:

# 最高效的判断值是否存在的方法
if Article.objects.filter(name='三国演义').exists():
  print(True)
# 比上面的方法效率低一点
if Article.objects.filter(name='三国演义').count() > 0:
  print(True)
# 还要比上面的效率低
if Article.objects.filter(name='三国演义'):
  print(True)

20. distinct:

去除掉那些重复的数据。这个方法如果底层数据库用的是MySQL,那么不能传递任何的参数。

需求:提取所有销售的价格超过80元的图书,并且删掉那些重复的,那么可以使用distinct来帮我们实现,示例代码如下:

books = models.Book.objects.filter(bookorder__price__gte=80).distinct()
  for book in books:
    print(book.name)

并且distinct只会剔除那些完全相同的数据,如果有一个字段不相同,都不会剔除的。

如果在distinct之前使用了order_by,那么因为order_by会提取order_by中指定的字段,因此再使用distinct就会根据多个字段来进行唯一化,所以就不会把那些重复的数据删掉。

示例:

orders = models.BookOrder.objects.order_by("pages").values("book_id").distinct()

21. update:

执行更新操作,在SQL底层走的也是update命令。比如要将所有图书的价格都提高10元。

book = models.Book.objects.update(price=F('price')+5)

22. delete:

删除所有满足条件的数据。删除数据的时候,要注意on_delete指定的处理方式。

例如删除作者id大于等于3的数据

result = models.Author.objects.get(id__gte=4).delete()

删除数据时一定要对你的表了如指掌,因为可能会牵连到很多其他数据。像在这个地方将这个作者删除了之后,那么这个作者对应的图书也将会被删除。

23. 切片操作:

有时候我们查找数据,有可能只需要其中的一部分。那么这时候可以使用切片操作来帮我们完成。QuerySet使用切片操作就跟列表使用切片操作是一样的。

# 获取1,2两条数据
  books = models.Book.objects.all()[1:3]
  for book in books:
    print(book)

以上这篇浅谈Django QuerySet对象(模型.objects)的常用方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python中日期和时间格式化输出的方法小结
Mar 19 Python
利用Python和OpenCV库将URL转换为OpenCV格式的方法
Mar 27 Python
Python实现网络端口转发和重定向的方法
Sep 19 Python
Centos7 Python3下安装scrapy的详细步骤
Mar 15 Python
mac安装scrapy并创建项目的实例讲解
Jun 13 Python
Python爬取qq空间说说的实例代码
Aug 17 Python
详解Python with/as使用说明
Dec 13 Python
python3安装speech语音模块的方法
Dec 24 Python
Python Web框架之Django框架cookie和session用法分析
Aug 16 Python
matplotlib.pyplot画图并导出保存的实例
Dec 07 Python
Pytest中skip和skipif的具体使用方法
Jun 30 Python
基于Python实现流星雨效果的绘制
Mar 18 Python
django使用F方法更新一个对象多个对象字段的实现
Mar 28 #Python
Django 拼接两个queryset 或是两个不可以相加的对象实例
Mar 28 #Python
使用Django实现把两个模型类的数据聚合在一起
Mar 28 #Python
使用python客户端访问impala的操作方式
Mar 28 #Python
python 安装impala包步骤
Mar 28 #Python
django 链接多个数据库 并使用原生sql实现
Mar 28 #Python
Django多数据库配置及逆向生成model教程
Mar 28 #Python
You might like
PHP MSSQL 存储过程的方法
2008/12/24 PHP
PHP基于curl实现模拟微信浏览器打开微信链接的方法示例
2019/02/15 PHP
js跟随滚动条滚动浮动代码
2009/12/31 Javascript
8个超棒的学习 jQuery 的网站 推荐收藏
2011/04/02 Javascript
基于jquery实现后台左侧菜单点击上下滑动显示
2013/04/11 Javascript
jquery win 7透明弹出层效果的简单代码
2013/08/06 Javascript
js和php如何获取当前url的内容
2013/09/22 Javascript
JS操作Cookies的小例子
2013/10/15 Javascript
解析JavaScript中delete操作符不能删除的对象
2013/12/03 Javascript
JavaScript获取元素尺寸和大小操作总结
2015/02/27 Javascript
js全选按钮的实现方法
2015/11/17 Javascript
使用jquery提交form表单并自定义action的实现代码
2016/05/25 Javascript
js Canvas实现圆形时钟教程
2016/09/19 Javascript
jquery购物车结算功能实现方法
2020/10/29 Javascript
jquery实现图片上传前本地预览
2017/04/28 jQuery
详解react如何在组件中获取路由参数
2017/06/15 Javascript
Angular.js ng-file-upload结合springMVC的使用教程
2017/07/10 Javascript
详解vue中使用express+fetch获取本地json文件
2017/10/10 Javascript
ligerUI---ListBox(列表框可移动的实例)
2017/11/28 Javascript
微信小程序实现留言板
2018/10/31 Javascript
vue-router 中 meta的用法详解
2019/11/01 Javascript
python中装饰器级连的使用方法示例
2017/09/29 Python
python实现txt文件格式转换为arff格式
2018/05/31 Python
详解python校验SQL脚本命名规则
2019/03/22 Python
python环境下安装opencv库的方法
2020/03/05 Python
Python如何使用正则表达式爬取京东商品信息
2020/06/01 Python
通过实例解析python and和or使用方法
2020/11/14 Python
HTML5 progress和meter控件_动力节点Java学院整理
2017/07/06 HTML / CSS
Desigual美国官方网站:西班牙服装品牌
2019/03/29 全球购物
大学班级计划书
2014/04/29 职场文书
村干部群众路线教育活动对照检查材料
2014/10/01 职场文书
开展党的群众路线教育实践活动总结报告
2014/10/31 职场文书
成绩单评语
2015/01/04 职场文书
创业计划书之o2o水果店
2019/08/30 职场文书
python自动化之如何利用allure生成测试报告
2021/05/02 Python
windows安装python超详细图文教程
2021/05/21 Python