【问题标题】:Django filter a reverse relationship of each item in a querysetDjango过滤查询集中每个项目的反向关系
【发布时间】:2015-06-29 10:04:01
【问题描述】:

所以我有 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

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

非常感谢任何帮助。

【问题讨论】:

  • UserQuestions.objects.filter(question__field=value) 有什么问题?
  • 我修改了我的问题并添加了更多信息。基本上我需要带有注释的用户,这就是为什么我不能从其他 2 个模型中做到这一点。获取每个用户并为每个用户过滤两次并制作列表也是不可能的,因为它需要太多并且对数据库进行太多查询。

标签: python django filter django-queryset


【解决方案1】:

你在正确的轨道上。

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

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

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

| 用于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]

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

【讨论】:

  • 对不起,我不明白,我该如何实现?我该怎么做?可以举个例子吗?>
  • 这种方法非常昂贵,如果我有很多数据,它会永远花费时间
  • 我看不出这种方法有多贵。它总共执行三个查询。如果这需要很长时间,那么在一个查询中执行此操作也将需要很长时间。
  • 要运行三个fors,在数千行数据上,查询不是这里昂贵的部分,for方法会花费很长时间
  • Django 将遍历获取的行并为每个行创建 User 实例以评估查询。所以无论如何你都有for循环。我的方法仍然只是一个比你所希望的慢的常数因素。我确信这个常数非常接近三。
猜你喜欢
  • 1970-01-01
  • 2019-11-06
  • 2021-11-02
  • 2016-11-07
  • 2016-01-26
  • 2012-11-18
  • 2017-11-07
  • 1970-01-01
  • 2011-03-23
相关资源
最近更新 更多