Django注释对另一个注释有副作用

2024-10-02 20:38:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我遇到了一个问题,向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的值是正确的。你知道吗

为什么?如何使两个注释都工作而不相互干扰?我试过各种各样的方法,但目前还不知道如何做到这一点。你知道吗


Tags: namemodelonmodelscountunitdeleteclass
1条回答
网友
1楼 · 发布于 2024-10-02 20:38:31

是的,因为现在有两个JOIN,而且^{} [Django-doc]是行数,因此它将充当某种乘数。你知道吗

但是,我们可以通过指定distinct=True来解决这个问题,比如:

Player.objects.annotate(
    rarity7_count=Count('unit_set', distinct=True, filter=Q(unit_set__rarity=7)),
    gear_count=Count('unit_set__ug_set')
).values_list('name', 'rarity7_count', 'gear_count')

请注意,如果希望gear_count也对稀有性进行过滤,则需要再次指定filter=部分。你知道吗

相关问题 更多 >