有时候,我们想要获取一个对象关联关系的数量,但是我们不要所有的关联对象,我们只想要符合规则的那些关联对象的数量。

示例models

# models.py
from django.db import models class Person(models.Model):
name = models.CharField('名称', max_length=32) def __str__(self):
return self.name class Task(models.Model):
name = models.CharField('任务名称', max_length=64)
is_done = models.BooleanField('是否完成', default=False)
owner = models.ForeignKey(Person, verbose_name='任务执行人') def __str__(self):
return "{}({})".format(self.name, 'x' if self.is_done else 'o')

上面的代码中,我们使用了两个model,PersonTask。它们是一对多关系,一个用户可能有多个任务。

那么,我们怎么来获取一个用户已完成任务的数量呢?

解决方法

一般来说,都是使用下面这个办法:

>>> person = Person.objects.first()
>>> person.task_set.all().count()
15
>>> person.task_set.filter(is_done=True).count()
10

这个办法,确实可以解决问题。但是如果你有很多Person,都需要获取已完成任务的数量,使用这个方法会依次对每个person的tasks集合使用单独的SQL,开销极大。

我们知道,Django ORM有一个aggregate函数,叫做Count。一般情况下,可以用它来获取一个对象关联对象的数量,并生成一个额外的computed字段。而在Django2.0中1Count新加入了一个参数filter,使用它,可以在计算count数量之前先对集合进行过滤

>>> from django.db.models import Count, Q
>>> person = Person.objects.annotate(
... Count('task_set', filter=Q(task_set__is_done=True))
... ).first()
>>> person.task_set__count
10

而在Django2.0之前,我们应该怎么办呢?可以用SQL的Case/When来解决:

>>> from django.db.models import Count, When, Case
>>> person = Person.objects.annotate(Count(Case(When(task_set__is_done=True, then=0))).first()
>>> person.task_set__count
10

Django ORM中,如何使用Count来关联对象的子集数量的更多相关文章

  1. 优化Django ORM中的性能问题(含prefetch_related 和 select_related)

    Django是个好工具,使用的很广泛. 在应用比较小的时候,会觉得它很快,但是随着应用复杂和壮大,就显得没那么高效了.当你了解所用的Web框架一些内部机制之后,才能写成比较高效的代码. 怎么查问题 W ...

  2. Django ORM 中的批量操作

    Django ORM 中的批量操作 在Hibenate中,通过批量提交SQL操作,部分地实现了数据库的批量操作.但在Django的ORM中的批量操作却要完美得多,真是一个惊喜. 数据模型定义 首先,定 ...

  3. django ORM中的复选MultiSelectField的使用

    下载和介绍: https://pypi.org/project/django-multiselectfield/ 在django ORM的使用中,经常会出现选择的情况,例如: class person ...

  4. django ORM中的RelatedManager(关联管理器)

    关联管理器应用在 一对多的表 或者 多对多的表 多对多表中的用法: 在多对多的表中 正向查询 #基于对象的查询 #正查 # author_obj = Author.objects.get(id=1) ...

  5. Django ORM中常用字段和参数

    一些说明: 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时. ...

  6. django ORM中的表关系

    多对一: 为了方便理解,两个表之间使用ForeignKey连接时,使用ForeignKey的字段所在的表为从表,被ForeignKey连接的表为主表. 使用场景:书和出版社之间的关系,一本书只能由一个 ...

  7. Django ORM中的查询,删除,更新操作

    ORM查询操作 修改views.py文件 from django.shortcuts import render, HttpResponse from app01 import models from ...

  8. Django ORM中的模糊查询

    ORM映射 什么是ORM映射?在笔者认为就是对SQL语句的封装,所写语句与SQL对应语句含义相同,使开发更加简单方便,不过也是存在弊端的,使程序运行效率下降.例如: UserInfo.objects. ...

  9. Django ORM性能优化之count和len方法的选择(非常详细推荐干货)

    接下来我将从源码层面分情况和应用分析我们在计算queryset数据集时是用orm的count函数计算长度还是用len函数计算数据集长度. 首先,我们知道ORM查询queryset数据集是惰性查询的,只 ...

随机推荐

  1. python第九章:面向对象--小白博客

     面向对象介绍 一.面向对象和面向过程 面向过程:核心过程二字,过程即解决问题的步骤,就是先干什么后干什么 基于该思想写程序就好比在这是一条流水线,是一种机械式的思维方式 优点:复杂的过程流程化 缺点 ...

  2. 让linux启动更快的方法

    导读 进行 Linux 内核与固件开发的时候,往往需要多次的重启,会浪费大把的时间. 在所有我拥有或使用过的电脑中,启动最快的那台是 20 世纪 80 年代的电脑.在你把手从电源键移到键盘上的时候,B ...

  3. PS制作简洁漂亮的立体抽丝文字

    一.新建一个800*600px文档,并将Background图层创建一个副本,将其命名为Background_copy. 二.双击Background_copy图层,勾选渐变叠加,并设定以下数值 勾选 ...

  4. Eclipse 查看 WebService 服务请求和响应消息

    每个WebService 对入参和返参都是有自己的要求的:别人调用我的WebService,需要按照我的要求进行传参.当我返回数据时,我也得告诉别人,我的返回数据是怎样组织的,方便别人读取. 那怎样查 ...

  5. centos值cron-计划任务

    一.crond简介 crond是Linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具.并且会自动启动cro ...

  6. 放弃幻想,全面拥抱Transformer:自然语言三大特征抽取器CNN/RNN/Transformer比较

    参考: https://zhuanlan.zhihu.com/p/54743941

  7. Python——字典操作

    一.取出字典中所有的key-value student={'name':'xiaoming','age':11,'school':'tsinghua'} for key,value in studen ...

  8. MySQL索引管理

    一.索引介绍 1.什么是索引 1.索引好比一本书的目录,它能让你更快的找到自己想要的内容. 2.让获取的数据更有目的性,从而提高数据库索引数据的性能. 2.索引类型介绍 1.BTREE:B+树索引 2 ...

  9. mysql数据去重并排序使用distinct 和 order by 的问题

    比如直接使用: SELECT distinct mobileFROM table_aWHERE code = 123ORDER BY a_ime desc 在本地mysql数据库没有错,在线上的数据库 ...

  10. mongoDB 小练习

    1 创建数据库名为 grade > use grade switched to db grade 2 创建集合 class 3 插入若干数据 格式如下{name:xxx,age:xxx,sex: ...