Мне нравится, как Django ORM лениво загружает связанные объекты в наборе запросов, но я думаю, что это довольно непредсказуемо.
API набора запросов не сохраняет связанные объекты, когда они используются для создания набора запросов, тем самым извлекая их снова при последующем доступе.
Предположим, у меня есть экземпляр ModelA (скажем, instance_a ), который является внешним ключом (скажем, for_a ) из нескольких N экземпляров ModelB . Теперь я хочу выполнить запрос к ModelB , у которого в качестве внешнего ключа задан экземпляр ModelA .
Django ORM предоставляет два способа:
- Использование
.filter()
на ModelB :
b_qs = ModelB.objects.filter(for_a=instance_a)
for instance_b in b_qs:
instance_b.for_a # <-- fetches the same row for ModelA again
Результатов здесь 1 + N запросов.
- Использование обратных отношений на ModelA экземпляр:
b_qs = instance_a.for_a_set.all()
for instance_b in b_qs:
instance_b.for_a # <-- this uses the instance_a from memory
Результаты только для 1 запроса здесь.
Хотя для достижения результата можно использовать второй способ, он не является частью стандартного API и не применим для каждого сценария. Например, если у меня есть экземпляры 2 внешних ключей ModelB (скажем, ModelA и ModelC ), и я хочу получить связанные объекты для них обоих.
Что-то вроде следующих работ:
ModelB.objects.filter(for_a=instance_a, for_c=instance_c)
Полагаю, для этого сценария можно использовать .intersection()
, но я бы хотел добиться этого через стандартный API. В конце концов, для покрытия таких случаев потребуется больше кода с нестандартными функциями набора запросов, что может не иметь смысла для следующего разработчика.
Итак, первый вопрос, возможно ли оптимизировать такие сценарии с помощью самого стандартного API?
Второй вопрос, если сейчас это невозможно, можно ли его добавить с помощью QuerySet с помощью некоторых настроек?
PS: Я впервые задаю вопрос здесь, так что извините, если я допустил ошибку.