Django 过滤符合 ManyToMany 中特定条件的行数
Django filter by the number of rows matching a certain condition in a ManyToMany
我需要过滤 ManyToMany 关系中元素数量与条件匹配的对象。以下是一些简化模型:
Place(models.Model):
name = models.CharField(max_length=100)
Person(models.Model):
type = models.CharField(max_length=1)
place = models.ManyToManyField(Place, related_name="people")
我试过这样做:
c = Count(Q(people__type='V'))
p = Places.objects.annotate(v_people=c)
但这只会让 .v_people
属性计算人数。
因为 python-2.0, you can use the filter=...
parameter of the Count(..)
function [Django-doc] 为此:
Place.objects.annotate(
v_people=Count('people'<b>, filter=Q(people__type='V')</b>)
)
所以这将分配给 v_people
具有 type='V'
的特定 Place
对象的人数。
另一种方法是 .filter(..)
首先是关系:
Place.objects.filter(
Q(people__type='V') | Q(people__isnull=True)
).annotate(
v_people=Count('people')
)
在这里我们过滤关系,这样我们允许 people
有 type='V'
,或者根本没有 people
(因为 Place
没有people
。我们再统计相关型号。
这会生成如下查询:
SELECT `place`.*, COUNT(`person_place`.`person_id`) AS `v_people`
FROM `place`
LEFT OUTER JOIN `person_place` ON `place`.`id` = `person_place`.`place_id`
LEFT OUTER JOIN `person` ON `person_place`.`person_id` = `person`.`id`
WHERE `person`.`type` = V OR `person_place`.`person_id` IS NULL
我需要过滤 ManyToMany 关系中元素数量与条件匹配的对象。以下是一些简化模型:
Place(models.Model):
name = models.CharField(max_length=100)
Person(models.Model):
type = models.CharField(max_length=1)
place = models.ManyToManyField(Place, related_name="people")
我试过这样做:
c = Count(Q(people__type='V'))
p = Places.objects.annotate(v_people=c)
但这只会让 .v_people
属性计算人数。
因为 python-2.0, you can use the filter=...
parameter of the Count(..)
function [Django-doc] 为此:
Place.objects.annotate(
v_people=Count('people'<b>, filter=Q(people__type='V')</b>)
)
所以这将分配给 v_people
具有 type='V'
的特定 Place
对象的人数。
另一种方法是 .filter(..)
首先是关系:
Place.objects.filter(
Q(people__type='V') | Q(people__isnull=True)
).annotate(
v_people=Count('people')
)
在这里我们过滤关系,这样我们允许 people
有 type='V'
,或者根本没有 people
(因为 Place
没有people
。我们再统计相关型号。
这会生成如下查询:
SELECT `place`.*, COUNT(`person_place`.`person_id`) AS `v_people`
FROM `place`
LEFT OUTER JOIN `person_place` ON `place`.`id` = `person_place`.`place_id`
LEFT OUTER JOIN `person` ON `person_place`.`person_id` = `person`.`id`
WHERE `person`.`type` = V OR `person_place`.`person_id` IS NULL