Я потратил некоторое время, пытаясь придумать способ построить хорошую фабрику для этого, но у меня много проблем с этим.
Лучшее, что я могу вам предложить, - это связать ваше наследство. Он не очень общий, поэтому я не уверен, насколько он полезен, но все, что вам нужно сделать, это:
class GlobalMixin(DeleteMixin):
is_global = models.BooleanField(default=True)
objects = GlobalManager()
class Meta:
abstract = True
class GlobalManager(DeleteManager):
def globals(self):
return self.get_query_set().filter(is_global=1)
Если вы хотите что-то более общее, лучшее, что я могу придумать, - это определить базу Mixin
и Manager
, которая переопределяет get_query_set()
(я предполагаю, что вы хотите сделать это только один раз; все становится довольно в противном случае сложно), а затем передайте список полей, которые вы хотите добавить, через Mixin
s.
Это будет выглядеть примерно так (совсем не проверено):
class DeleteMixin(models.Model):
deleted = models.BooleanField(default=False)
class Meta:
abstract = True
def create_mixin(base_mixin, **kwargs):
class wrapper(base_mixin):
class Meta:
abstract = True
for k in kwargs.keys():
setattr(wrapper, k, kwargs[k])
return wrapper
class DeleteManager(models.Manager):
def get_query_set(self):
return super(DeleteManager, self).get_query_set().filter(deleted=False)
def create_manager(base_manager, **kwargs):
class wrapper(base_manager):
pass
for k in kwargs.keys():
setattr(wrapper, k, kwargs[k])
return wrapper
Хорошо, так это безобразно, но что это тебе дает? По сути, это то же решение, но гораздо более динамичное и немного более СУХОЕ, хотя и более сложное для чтения.
Сначала вы динамически создаете своего менеджера:
def globals(inst):
return inst.get_query_set().filter(is_global=1)
GlobalDeleteManager = create_manager(DeleteManager, globals=globals)
Это создает нового менеджера, который является подклассом DeleteManager
и имеет метод с именем globals
.
Далее вы создаете свою модель миксина:
GlobalDeleteMixin = create_mixin(DeleteMixin,
is_global=models.BooleanField(default=False),
objects = GlobalDeleteManager())
Как я уже сказал, это ужасно. Но это означает, что вам не нужно переопределять globals()
. Если вы хотите, чтобы у другого типа менеджера был globals()
, просто позвоните create_manager
снова с другой базой. И вы можете добавить столько новых методов, сколько захотите. То же самое для менеджера, вы просто продолжаете добавлять новые функции, которые будут возвращать разные наборы запросов.
Итак, это действительно практично? Возможно, нет. Этот ответ - скорее упражнение в (ab) с использованием гибкости Python. Я не пробовал использовать это, хотя я использую некоторые базовые принципы динамически расширяемых классов, чтобы облегчить доступ к ним.
Дайте мне знать, если что-то неясно, и я обновлю ответ.