Выберите, какой менеджер моделей использовать при выполнении 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()
Вернуться на верх