我正在用Count注释QuerySet,但是我只想对某些对象进行计数,因此我正在使用过滤器:
objects = Parent.objects.annotate(num_children=Count('child',filter=Q(deleted_at=None)))
过滤器不起作用,每个对象的计数似乎都忽略了过滤器,即,它也计算了具有过滤器的子容器
deleted_at != None
模型:
class child(models.Model):
parent = models.ForeignKey('project.Parent', on_delete=models.CASCADE)
deleted_at = models.DateTimeField(blank=True, null=True)
有人有解决方案吗? 预先感谢。
修改
使用Q(deleted_at__isnull=True)
也不起作用。与~Q(deleted_at=None)
奇怪的是,我得到了预期的行为...
答案 0 :(得分:3)
使用 Q(...)
对象进行过滤时,必须提供关于 Parent
模型的查找。
因此,它应该是 filter=Q(child__deleted_at=None)
而不是filter=Q(deleted_at=None)
objects = Parent.objects.annotate(
num_children=Count('child', filter=Q(child__deleted_at=None))
)
为重现错误/问题行为,我创建了以下两个简单模型,
class Parent(models.Model):
name = models.CharField(max_length=50)
class Meta:
db_table = 'parent_table'
def __str__(self):
return self.name
class Child(models.Model):
parent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name='children')
deleted_at = models.DateTimeField(blank=True, null=True)
class Meta:
db_table = 'child_table'
def __str__(self):
return f'{self.parent} -- {self.deleted_at}'
注释:
我设置了related_name='children'
,它在查询反向关系时更“有意义”。如果您不熟悉related_name
,请阅读更多
a。 What is related_name
in Django -- (SO Post)
我已经设置了db_table
,因为某些原因,我将使用RawSQL查询数据库。您不必进行设置。
现在,我在数据库中填充了一些虚拟数据,结果如下:
然后我打开Django shell并运行以下查询,
In [2]: from django.db.models import Q,Count
In [3]: parent_objects = Parent.objects.annotate(
...: num_children=Count('children', filter=Q(children__deleted_at=None))
...: )
In [4]: for parent in parent_objects:
...: print(parent.id, '--', parent.name, ' :: ', parent.num_children)
...:
1 -- parent-1 :: 2
2 -- parent-2 :: 0
3 -- parent-3 :: 1
或者, 原始SQL视图,