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

时间:2015-06-29 10:04:01

标签: python django filter django-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并使用问题字段使用transwer_set,然后使用countquestions_set和useranswer_set之和的计数来注释查询集。

如果我这样做:

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

它过滤我的用户,我想过滤他们的用户问题集和useranswers,以便它们只包含那个字段与我的值相等的问题,以便为查询集中的行获得正确的注释。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

你走在正确的轨道上。

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

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]

我们的想法是,我们可以通过三个简单的查询来完成所有操作,因为只有一个查询不可能。