简体   繁体   English

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

[英]Django filter a reverse relationship of each item in a queryset

So i have 3 models 所以我有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)

I want to get a list of all the users, but i want to filter their userquestion_set and useranswer_set by a field of the question and then annotate the queryset with a count for the sum of userquestions_set and useranswer_set. 我想获取所有用户的列表,但是我想通过问题字段过滤他们的userquestion_set和useranswer_set,然后用userquestions_set和useranswer_set之和的计数来注释查询集。

if i do something like: 如果我做类似的事情:

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

It filters my Users, i want to filter their set of userquestions and useranswers so that they contain only the questions which have that field equal with my value, in order to get a proper annotation for the rows in the queryset. 它过滤了我的用户,我想过滤他们的一组用户问题和用户答案,以便它们仅包含具有与我的值相同的字段的问题,以便为查询集中的行获得正确的注释。

Any help is much appreciated. 任何帮助深表感谢。

You are on the right track. 您走在正确的轨道上。

The resulting rows that your query will be evaluated across are similar to: 您的查询将被评估的结果行类似于:

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

for all combinations of User , UserQuest and UserAnswer where *__user_id equals id . 对于UserUserQuestUserAnswer所有组合,其中*__user_id等于id So when you & your Q objects together, you only consider rows that match both Q objects. 因此,当您&您的Q对象一起使用时,您只考虑同时匹配两个Q对象的行。 This is why your annotations will only work for users having both questions and answers that match your criteria. 这就是为什么您的注释仅对具有符合您条件的问题和答案的用户有效的原因。 All other User s are filtered away. 其他所有User均被过滤掉。

Using | 使用| for the Q objects won't help you much either, because the unmatched criteria will count as false positives and vice versa. 对于Q对象也不会有太大帮助,因为不匹配的条件将被视为误报,反之亦然。

So your only option is to first load all the users, then load all the users with the right answer annotated with answer count, and then load all the users with the right question annotated with question count. 因此,您唯一的选择是首先加载所有用户,然后使用正确的答案和答案计数加载所有用户,然后使用正确的问题和答案计数加载所有用户。 Finally you should annotate users with the relevant counts. 最后,您应该为用户添加相关计数。

Edit (Example): The following is not tested, and I apology for my rusty Python: 编辑(示例):以下内容未经测试,我为生锈的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]

The idea is that we get to do everything in three simple queries, since it is not possible to do in just one. 这样做的想法是,我们无法通过三个简单的查询来完成所有操作,因为不可能只执行一个查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM