计数前排除相关对象

时间:2018-10-09 12:51:30

标签: django django-orm

例如,我有3个模型UserAB

class A(models.Model):
    creator = models.ForeignKey(
        'users.User', on_delete=models.CASCADE, related_name='A_set'
    )


class B(models.Model):
    user = models.ForeignKey(
        'users.User', on_delete=models.CASCADE, related_name='B_set'
    )
    a_model = models.ForeignKey(
        'a.A', on_delete=models.CASCADE, related_name='B_set'
    )

我想获得B的数量,其中user不是a_model对象的creator

我尝试查询:

`User.objects.prefetch_related('B_set').last().B_set.exclude(a_model__creator=F('user')).count()`

这是我尝试使用注释的方法:

User.objects.annotate(b_count=Count('B_set', filter=(~Q(B_set__A__creator=F('user')))))

但是我遇到一个错误:

  

无法将关键字“用户”解析为字段。

然后它建议我与用户有关的字段。我也尝试用userB_set__user更改为F(),但没有帮助。

1 个答案:

答案 0 :(得分:1)

带有注释:

User.objects.annotate(
    b_count=Count('B_set', filter=(~Q(B_set__A__creator=F('user'))))
)

您的F(..)属性指的是假设的 User.user字段,但是User(可能)没有user字段。

如果您想在此处引用“自我”,则可以使用F('pk')(或F('id'),前提是id是主键),因此可以编写此表达式为:

User.objects.annotate(
    b_count=Count('B_set', filter=~Q(B_set__a__model__creator=F('pk')))
)

这将导致如下查询:

SELECT user.*,
       COUNT(
           CASE WHEN NOT a.creator_id = user.id AND a.creator_id IS NOT NULL
           THEN b.id ELSE NULL END
       ) AS b_count
FROM user
LEFT OUTER JOIN b ON user.id = b.user_id
LEFT OUTER JOIN a ON b.a_model_id=a.id
GROUP BY user.id