Один пользовательский менеджер для нескольких моделей в Django
У меня есть несколько моделей, связанных друг с другом отношениями ForeignKeys.
Основная в этой иерархии содержит поле владельца.
Я хотел бы создать единый пользовательский менеджер для всех этих моделей, который изменяет возвращаемый набор запросов в зависимости от моделей, которые его вызывают.
Я знаю, что менеджер может получить доступ self.model
чтобы получить модель, к которой он прикреплен.
Class Main(models.Model)
owner=models.ForeignKey (User)
owned = OwnedManager()
Class Second(models.Model)
main=models.ForeignKey('Main')
owned = OwnedManager()
Class Third(models.Model)
second=models.ForeignKey('Second')
owned = OwnedManager()
Я бы хотел, чтобы мой Custom Manager имел такое поведение:
class OwnedManager(models.Manager):
def get_owned_objs(self, owner):
if self.model == 'Main': # WRONG: How do I get the model name?
owned_main = self.filter(owner=owner)
return owned_main
elif self.model == 'Second':
owned_second = self.filter(main__owner=owner)
return owned_second
else:
owned_third = self.filter(second__main__owner=owner)
return owned_third
Для того, чтобы иметь последовательный способ вызывать его в разных моделях, вот так:
main_object.owned.get_owned_objs(owner=user1) # of the Model Main
second_object.owned.get_owned_objs(owner=user1) # of the Model Second
third_object.owned.get_owned_objs(owner=user1) # of the Model Third
ВОПРОС:
self.model == 'Main'
неправильно. Я не получаю название модели, как это. Есть ли способ получить это?- Это эффективно? Знаете ли вы лучший способ реализовать это? Может быть, Наследование пользовательских менеджеров?
РЕДАКТИРОВАТЬ - МОЕ РЕШЕНИЕ. Принятый ответ ниже является хорошим решением, но я также нашел способ получить имя модели конкретной модели, вызывающей пользовательский менеджер, а именно:
if self.model.__name__ == 'Main':
Ключ здесь является атрибутом __name__
1 ответ
1) Сделать абстрактную модель
class AbstractModel(models.Model):
class Meta(models.Meta):
abstract = True
objects = OwnedManager()
2) Унаследуйте ваши модели от AbstractModel, поместите некоторые ключи в мета
class Model(AbstractModel)
class Meta(AbstractModel.Meta):
filter_key = 'some_key'
3) Редизайн вашего OwnedManager
class OwnedManager(models.Manager):
def get_owned_objs(self, owner):
if hasattr(self.model._meta, 'filter_key'):
return self.filter(**{self.model._meta.filter_key: owner})
Теперь вы можете использовать SomeModel.objects.get_owned_objs(owner=user1)
в любых унаследованных моделях, где filter_key
устанавливается без получения названия модели.