只使用Django选择相关对象的子集

时间:2014-05-27 22:45:22

标签: python django django-models

考虑以下模型:

class Question(models.Model):
    ...

class Answer(models.Model):
    user = models.ForeignKey('auth.User')
    question = models.ForeignKey(Question)
    answer = models.TextField(...)
    class Meta:
        unique_together = ('user', 'question'),

现在在视图中我想迭代一些问题并使用request.user中的(仅可能存在的)答案,如:

questions = Questions.objects.filter(...).iterator()
for q in questions:
    try:
        a = Answer.objects.get(user=request.user, question=q)
    except Answer.DoesNotExist:
        a = None
    do_something_with(a)

这导致O(#Questions)数据库命中。我可以使用.prefetch_related(),但我没有看到一种方法来限制使用Answer预取到user=request.user的值,并且在拥有大量用户的网站上需要花费相当多的金额用于预取所有用户的答案的内存。

我认为可以使用.extra()在单个查询中检索信息。我还没有对它进行测试,但我希望以下内容能够正常工作:

questions = Questions.objects.extra(select={'user_answer': 'SELECT id, answer from answer where answer.user.id = %s', }, params=(request.user.id,))

(如果没有可用的答案,不确定这是如何表现的。)

Questions.objects.filter(answer__user=request.user)无法正常工作,因为它会跳过Answer之前没有相关request.user的问题。

还使用两个查询:

questions = Question.objects.filter(...).all()
users_answers = Answer.objects.filter(user=request.user, question__in=questions)
users_answers = dict((a.id, a) for a in users_answers)
for q in questions:
    a = users_answers.get(q.id)
如果有许多问题与使用过的过滤器匹配,则

效率低下。

是否有更多的pythonic方式不会强迫我编写SQL,更容易编写和读取,并且仍然比逐个获取Answer的第一个变体更有效在Python循环中?

0 个答案:

没有答案