#django #nested #prefetch
#django #вложенный #предварительная выборка
Вопрос:
У меня есть информационная модель с глубокими и сложными отношениями внешнего ключа. и их много. Из-за этого я пытаюсь использовать select_related()
и prefetch_related()
для минимизации количества запросов к моей базе данных.
Однако у меня проблема в том, что я не могу найти способ заставить операторы предварительной выборки следовать за внешними ключами на произвольную глубину. Я знаю об операторе двойного подчеркивания ( __
), но на самом деле это не вариант, потому что я заранее не знаю, насколько глубокой будет вложенность.
Итак, допустим, у меня есть объекты A, B, C,...Z
. Любой объект может иметь произвольное количество внешних ключей, указывающих на любой объект, который появляется, скажем, позже в алфавите. Как я могу убедиться, что, например, предварительная выборка внешнего ключа, который A
указывает на B
, будет следовать за всеми внешними ключами в B?
Моим лучшим решением на данный момент был полужестко закодированный подход к get_queryset()
методу диспетчера объектов.
Заранее благодарю вас
Редактировать:
Хорошо, итак, идея о том, как я пытаюсь это сделать на данный момент, заключается в следующем:
class MyModelmanager(model.Manger):
def get_queryset()
qs = super().get_queryset()
qs = qs.select_related(*thefiledsiwannaprefetch)
return qs
Теперь в полях, которые я предварительно выбираю, есть отношения внешних ключей, за которыми я хотел бы следить. Как мне этого добиться (без использования '__'
)?
РЕДАКТИРОВАТЬ 2
Другая попытка была следующей:
class MyModelmanager(model.Manger):
def get_queryset()
return super().get_queryset().prefetch_related()
Затем я переопределил управление другими моделями, чтобы они также выполняли предварительную выборку в своем get_queryset()
методе. Это также не сработало.
Комментарии:
1. Опубликуйте код того, как вы пытаетесь это сделать.
2. Если вы выполняете сериализацию, у DRF есть
depth
. Если вы отправляете данные в шаблон, в какой-то момент кода вы действительно что-то сделаете с данными, и обычно именно здесь вы создаете запросы для извлечения нужных вам данных, не меньше и не больше. Описанный подход по существу извлекает все данные из базы данных. Интересно, каким может быть вариант использования для этого. В любом случае, вам потребуется отражение , чтобы сделать это сprefetch_related
.
Ответ №1:
Из документов:
Могут возникнуть ситуации, когда вы захотите вызвать select_related() с большим количеством связанных объектов или когда вы не знаете всех отношений. В этих случаях можно вызвать select_related() без аргументов. Это будет следовать за всеми ненулевыми внешними ключами, которые он может найти — должны быть указаны внешние ключи с возможностью обнуления. В большинстве случаев это не рекомендуется, поскольку это, вероятно, усложнит базовый запрос и вернет больше данных, чем на самом деле необходимо.
Комментарии:
1. Ага, видел это. Я также пытался и потерпел неудачу с треском. Есть предложения о том, как это было бы реализовано на практике?
2. Вы вызвали без каких-либо аргументов, и это не сработало?
3. Чтобы было ясно, это не относится к
prefetch_related
. Пустойprefetch_related
вызов ничего не делает.