Django 过滤查询集中每个项目的反向关系

Django filter a reverse relationship of each item in a queryset

所以我有 3 个模型

class User(models.Model):

class UserQuestions(models.Model):
      user = models.ForeignKey(User)
      question = models.ForeignKey(Question)

class UserAnswers(models.Model):
      user = models.ForeignKey(User)
      question = models.ForeignKey(Question)

我想获取所有用户的列表,但我想通过问题的字段过滤他们的 userquestion_set 和 useranswer_set,然后用总和的计数来注释查询集userquestions_set 和 useranswer_set.

如果我做类似的事情:

User.objects.filter(Q(userquestions__question_field=value)&Q(useranswers__question_field=value)).annotate

它过滤我的用户,我想过滤他们的一组用户问题和用户答案,以便它们仅包含该字段与我的值相等的问题,以便为查询集中的行获得正确的注释。

非常感谢任何帮助。

你走在正确的轨道上。

您的查询将被评估的结果行类似于:

id | userquestion__id | userquestion__user_id | userquestion__value | usweranswer__id | useranswer__user_id | useranswer__value

对于 UserUserQuestUserAnswer 的所有组合,其中 *__user_id 等于 id。因此,当您 & 您的 Q 对象在一起时,您只考虑匹配两个 Q 对象的行。这就是为什么您的注释仅适用于问题和答案均符合您的标准的用户。所有其他 User 都被过滤掉。

Q 对象使用 | 也无济于事,因为不匹配的标准将被视为误报,反之亦然。

所以你唯一的选择是首先加载所有用户,然后加载所有用户的正确答案并标注答案数,然后加载所有用户正确的问题并标注问题数。最后,您应该使用相关计数来注释用户。

编辑(示例): 以下未经测试,生疏之处敬请见谅Python:

users = User.objects.all()
users_with_right_answers = defaultdict(
    int,
    {
        user.id: user.right_answer_count for user in User.objects.filter(
            useranswer__value='...').annotate(
            right_answer_count=Count('useranswer')
    }
)
users_with_right_questions = defaultdict(
    int,
    {
        user.id: user.right_question_count for user in User.objects.filter(
            userquestion__value='...').annotate(
            right_question_count=Count('userquestion')
    }
)

for user in users:
    user.right_answer_count = users_with_right_answers[user.id]
    user.right_question_count = users_with_right_questions[user.id]

我们的想法是,我们可以在三个简单的查询中完成所有事情,因为不可能只在一个查询中完成。