Выберите, какой менеджер моделей использовать при выполнении prefetch_related?
У меня есть модель Product в моем приложении Django, которая использует пользовательский менеджер моделей, где все prefetch_related
утверждения:
class ProductManager(models.Manager):
def get_queryset(self):
return (
super()
.get_queryset()
.select_related("core_product")
.prefetch_related("images")
.prefetch_related("bundled_products")
)
class Product(models.Model):
_base_manager = ProductManager
objects = ProductManager()
# ... model fields
Это работает отлично; когда я использую ORM и внутри Admin, используется пользовательский менеджер, предотвращая целую кучу дублирующих запросов.
Проблема возникает, когда у меня есть другая модель, которая имеет prefetch_related
к модели Product: теперь она наследует все prefetch_related
от Product, хотя в этом нет необходимости. Это вызывает целую кучу ненужных запросов.
class OfferManager(models.Manager):
def get_queryset(self):
return (
super()
.get_queryset()
.select_related("flag")
.prefetch_related("condition_products")
.prefetch_related("limited_to_users")
.order_by("-priority")
)
Здесь полем condition_products
является модель Product, описанная выше, и просто включив это поле prefetch_related
, все его утверждения prefetch_related
также наследуются. Как я могу предотвратить это? Могу ли я указать, какой менеджер объектов использовать в prefetch_related
- так, чтобы использовался "голый" менеджер?
Добавьте простой менеджер в Product
:
class Product(models.Model):
_base_manager = ProductManager
objects = ProductManager()
_simple_manager = models.Manager()
и затем использовать этот менеджер с Prefetch
объектом [Django-doc]:
from django.db.models import Prefetch
class OfferManager(models.Manager):
def get_queryset(self):
return (
super()
.get_queryset()
.select_related('flag')
.prefetch_related(
Prefetch('condition_products', Product._simple_manager.all()),
'limited_to_users',
)
.order_by('-priority')
)
Сначала я выбрал решение от willeM_ Van Onsem, с _simple_manager
, а затем использовал этот _simple_manager
в prefetch_related
. Но в конце концов я все переделал: по умолчанию используется обычный менеджер, а я использую пользовательский, в котором есть утверждения prefetch_related
. Теперь в моих представлениях я явно использую пользовательский менеджер, а все остальное по умолчанию использует обычный менеджер. Это кажется немного понятнее, чем иногда переопределять менеджер, используемый в утверждениях prefetch_related
.
class Product(models.Model):
_base_manager = ProductManager
objects = models.Manager()
prefetched_objects = ProductManager()