Подтвердить что ты не робот

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')

Обычно, чтобы получить количество ответов на вопрос, наиболее эффективным способом получить это было бы сделать следующее (поскольку в документах Django указано, что count() более эффективен, если вам просто нужен счетчик):

# Note: "question" is an instance of class Question.
answer_count = question.answers.count()

Однако в некоторых случаях ответы могли быть получены с помощью вызова prefetch_related() (или каким-то образом, например, ранее повторяющегося в ответах). Поэтому в таких ситуациях было бы более эффективно это делать (потому что мы пропустили дополнительный счетчик):

# Answers were fetched via prefetch_related()
answer_count = len(question.answers.all())

То, что я действительно хочу сделать, это что-то вроде:

if question.answers_have_been_prefetched:  # Does this exist?
  answer_count = len(question.answers.all())
else:
  answer_count = question.answers.count()

Я использую Django 1.4, если это имеет значение. Спасибо заранее.

Изменить: добавлено разъяснение, что prefetch_related() - это не единственный способ получить ответы.

4b9b3361

Ответ 1

Да, Django сохраняет предварительно выбранные результаты в атрибуте _prefetched_objects_cache экземпляра родительской модели.

Итак, вы можете сделать что-то вроде:

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

try:
    instance._prefetched_objects_cache[instance.children.prefetch_cache_name]
    # Ok, it pefetched
    child_count = len(instance.children.all())
except (AttributeError, KeyError):
    # Not prefetched
    child_count = instance.children.count()

См. соответствующее использование в исходной магистрали django или эквивалент в версии 1.4.9