Мне было интересно, возможно ли (и если да, как) объединить несколько менеджеров для создания набора запросов, на который влияют оба отдельных менеджера. Я объясню конкретный пример, над которым я работаю:
У меня есть несколько классов абстрактных моделей, которые я использую для обеспечения небольших, специфических функций для других моделей. Две из этих моделей - это DeleteMixin и GlobalMixin.
DeleteMixin определяется как таковой:
class DeleteMixin(models.Model):
deleted = models.BooleanField(default=False)
objects = DeleteManager()
class Meta:
abstract = True
def delete(self):
self.deleted = True
self.save()
В основном он предоставляет псевдо-удаление (удаленный флаг) вместо фактического удаления объекта.
GlobalMixin определяется как таковой:
class GlobalMixin(models.Model):
is_global = models.BooleanField(default=True)
objects = GlobalManager()
class Meta:
abstract = True
Он позволяет определять любой объект как глобальный объект или частный объект (например, публичный/закрытый блог).
У обоих из них есть свои собственные менеджеры, которые влияют на возвращаемый запрос. Мой DeleteManager фильтрует запрос, чтобы возвращать результаты только с установленным флажком False, в то время как GlobalManager фильтрует запрос, чтобы возвращать результаты, отмеченные как глобальные. Вот объявление для обоих:
class DeleteManager(models.Manager):
def get_query_set(self):
return super(DeleteManager, self).get_query_set().filter(deleted=False)
class GlobalManager(models.Manager):
def globals(self):
return self.get_query_set().filter(is_global=1)
Желаемая функциональность заключалась бы в том, чтобы модель расширяла обе эти абстрактные модели и предоставляла возможность возвращать только те результаты, которые не были удалены и глобальны. Я проверил тестовый пример на модели с 4 экземплярами: один был глобальным и не удалялся, один был глобальным и удалялся, один был неглобальным и не удалялся, а один был неглобальным и удалялся. Если я попытаюсь получить набор результатов как таковой: SomeModel.objects.all(), я получаю экземпляр 1 и 3 (два не удаленных - отлично!). Если я попробую SomeModel.objects.globals(), я получаю сообщение об ошибке, которое DeleteManager не имеет глобальных переменных (это предполагает, что мое объявление модели таково: SomeModel (DeleteMixin, GlobalMixin). Если я отменил порядок, t получить ошибку, но она не отфильтровывает удаленные). Если я изменю GlobalMixin, чтобы привязать GlobalManager к глобальным переменным вместо объектов (поэтому новой командой будет SomeModel.globals.globals()), я получаю экземпляры 1 и 2 (два глобальных символа), в то время как мой предполагаемый результат будет состоять только в том, чтобы получить экземпляр 1 (глобальный, не удаленный).
Я не был уверен, что кто-то столкнулся с ситуацией, подобной этому, и пришел к результату. Либо способ заставить его работать в моем текущем мышлении, либо переработать, который обеспечивает функциональность, с которой я буду, очень ценится. Я знаю, что этот пост был немного длинным. Если потребуется больше объяснений, я был бы рад предоставить его.
Edit:
Я опубликовал возможное решение, которое я использовал для этой конкретной проблемы ниже. Он основан на ссылке на пользовательский QuerySetManager Саймона.