Django:你能说出相关字段是否已被预取而没有取出它?

Cha*_*had 18 python django

我想知道Django是否有办法判断一个相关字段,特别是一对多关系中的"很多"部分是否已经通过,例如,prefetch_related()没有实际获取它?

所以,举个例子,假设我有这些模型:

class Question(Model):
  """Class that represents a question."""

class Answer(Model):
  """Class the represents an answer to a question."""
  question = ForeignKey('Question', related_name='answers')
Run Code Online (Sandbox Code Playgroud)

通常,要获得问题的答案数,最有效的方法是执行以下操作(因为Django文档说明count()如果您只需要计数则更有效):

# Note: "question" is an instance of class Question.
answer_count = question.answers.count()
Run Code Online (Sandbox Code Playgroud)

然而,在某些情况下,答案可能是通过prefetch_related()调用(或某种方式,例如先前已经遍历答案)获取的.所以在这种情况下,执行此操作会更有效(因为我们会跳过额外的计数查询):

# Answers were fetched via prefetch_related()
answer_count = len(question.answers.all())
Run Code Online (Sandbox Code Playgroud)

所以我真正想做的是:

if question.answers_have_been_prefetched:  # Does this exist?
  answer_count = len(question.answers.all())
else:
  answer_count = question.answers.count()
Run Code Online (Sandbox Code Playgroud)

如果重要的话,我正在使用Django 1.4.提前致谢.

编辑:添加澄清,这prefetch_related()不是获取答案的唯一方式.

Kev*_*one 24

是的,Django将预取结果存储_prefetched_objects_cache在父模型实例的属性中.

所以你可以这样做:

instance = Parent.objects.prefetch_related('children').all()[0]

try:
    instance._prefetched_objects_cache[instance.children.prefetch_cache_name]
    # Ok, it's pefetched
    child_count = len(instance.children.all())
except (AttributeError, KeyError):
    # Not prefetched
    child_count = instance.children.count()
Run Code Online (Sandbox Code Playgroud)

请参阅django源中继中的相关用法或v1.4.9中的等效用法

  • 将"Ok,它的prefetched"代码放入[`try`块的[`try ... except ... else`](https://docs.python.org/2/reference/compound_stmts.html#)可能是一个好主意.在试语句). (3认同)
  • 谢谢你,但我应该澄清一下: prefetch_lated 只是一个例子。也可以通过其他方式获取结果(例如迭代代码中之前的问题.答案)。 (2认同)
  • 相关管理器访问通常不会被缓存,您可能必须实现自己的memoization包装器:https://docs.djangoproject.com/en/dev/topics/db/optimization/#understand-queryset-evaluation (2认同)