Django 注解对另一个注解有副作用
Django annotation has side effect on another annotation
我 运行 遇到一个问题,即向 QuerySet 添加注释会更改先前注释的结果。
这是(简化的)设置:
class Player(models.Model):
name = models.CharField()
class Unit(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE,
related_name='unit_set')
rarity = models.IntegerField()
class Gear(models.Model):
pass
class UnitGear(models.Model):
unit = models.ForeignKey(Unit, on_delete=models.CASCADE,
related_name='ug_set')
gear = models.ForeignKey(Gear, on_delete=models.PROTECT)
用稀有度为 7 的单位注释玩家效果很好:
Player.objects.annotate(
rarity7_count=Count(unit_set__rarity=7)
).values_list('name', 'rarity7_count')
[('Player1', 170),
('Player2', 172),
('Player3', 164),
...,
)]
上面 rarity7_count
返回的值是正确的。
如果我添加下面的附加注释,就不再是这样了:
Player.objects.annotate(
rarity7_count=Count(unit_set__rarity=7),
gear_count=Count(unit_set__ug_set)
).values_list('name', 'rarity7_count', 'gear_count')
[('Player1', 476, 456),
('Player2', 490, 466),
('Player3', 422, 433),
...,
)]
请注意 rarity7_count
值发生了怎样的变化——这些值不再正确!但是,gear_count
的值是正确的。
这是为什么?如何让两个注释在不相互干扰的情况下工作?我已经尝试了各种各样的事情,但目前不知道该怎么做。
是,因为现在有两个JOIN
,而Count(..)
[Django-doc]是行数,所以会起到某种作用乘数。
但是我们可以通过指定 distinct=True
来解决这个问题,例如:
Player.objects.annotate(
rarity7_count=Count('unit_set'<b>, distinct=True</b>, filter=Q(unit_set__rarity=7)),
gear_count=Count('unit_set__ug_set')
).values_list('name', 'rarity7_count', 'gear_count')
请注意,如果您希望 gear_count
也过滤稀有度,您需要再次指定 filter=
部分。
我 运行 遇到一个问题,即向 QuerySet 添加注释会更改先前注释的结果。
这是(简化的)设置:
class Player(models.Model):
name = models.CharField()
class Unit(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE,
related_name='unit_set')
rarity = models.IntegerField()
class Gear(models.Model):
pass
class UnitGear(models.Model):
unit = models.ForeignKey(Unit, on_delete=models.CASCADE,
related_name='ug_set')
gear = models.ForeignKey(Gear, on_delete=models.PROTECT)
用稀有度为 7 的单位注释玩家效果很好:
Player.objects.annotate(
rarity7_count=Count(unit_set__rarity=7)
).values_list('name', 'rarity7_count')
[('Player1', 170),
('Player2', 172),
('Player3', 164),
...,
)]
上面 rarity7_count
返回的值是正确的。
如果我添加下面的附加注释,就不再是这样了:
Player.objects.annotate(
rarity7_count=Count(unit_set__rarity=7),
gear_count=Count(unit_set__ug_set)
).values_list('name', 'rarity7_count', 'gear_count')
[('Player1', 476, 456),
('Player2', 490, 466),
('Player3', 422, 433),
...,
)]
请注意 rarity7_count
值发生了怎样的变化——这些值不再正确!但是,gear_count
的值是正确的。
这是为什么?如何让两个注释在不相互干扰的情况下工作?我已经尝试了各种各样的事情,但目前不知道该怎么做。
是,因为现在有两个JOIN
,而Count(..)
[Django-doc]是行数,所以会起到某种作用乘数。
但是我们可以通过指定 distinct=True
来解决这个问题,例如:
Player.objects.annotate(
rarity7_count=Count('unit_set'<b>, distinct=True</b>, filter=Q(unit_set__rarity=7)),
gear_count=Count('unit_set__ug_set')
).values_list('name', 'rarity7_count', 'gear_count')
请注意,如果您希望 gear_count
也过滤稀有度,您需要再次指定 filter=
部分。