子类化models.Manager
Posted
技术标签:
【中文标题】子类化models.Manager【英文标题】:subclassing models.Manager 【发布时间】:2012-01-28 06:35:34 【问题描述】:我认为子类化models.manager
对象和覆盖get_query_set
方法或简单地在子类中创建一个新方法并使用该方法没有区别。原因是我从 django 书中举例;
class MaleManager(models.Manager):
def get_query_set(self):
return super(MaleManager, self).get_query_set().filter(sex='M')
class FemaleManager(models.Manager):
def get_query_set(self):
return super(FemaleManager, self).get_query_set().filter(sex='F')
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female')))
people = models.Manager()
men = MaleManager()
women = FemaleManager()
有了这个我可以使用; Person.women.all()
或 Person.men.all()
获取所有男性或女性模型对象。但是,我想类似的事情可以在不覆盖get_query_set
方法的情况下通过简单地实现;
class MaleManager(models.Manager):
def get_male(self):
return self.filter(sex='M')
class FemaleManager(models.Manager):
def get_female(self):
return return self.filter(sex='F')
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female')))
people = models.Manager()
men = MaleManager()
women = FemaleManager()
现在,有了这个,我可以用一点技术来获取所有这些对象:
Person.objects.get_male()
或 Person.objects.get_female()
。但是,我如何获取对象之间没有任何细微的区别,但在第一种情况下的可读性和使用方面存在差异,而第二种情况更容易理解并且代码更少。它们在编码和模式?第二个的另一件事是,如果我将这两个方法放在同一个类中会怎样;
class PeopleManager(models.Manager):
def get_male(self):
return self.filter(sex='M')
def get_female(self):
return return self.filter(sex='F')
【问题讨论】:
如果您只有 2 种方法,那么拥有完全独立的经理所提供的组织不值得麻烦 - 不知道为什么 django 书会建议使用 FemaleManager 和 MaleManager 而不是 get_females 和单个管理器上的 get_males 方法。 这更多地取决于您的抽象层。如果您打算拥有PeopleManager
,它只是按性别区分人,第二个选项更有用。如果将来例如 FemaleManager
将有像 get_blondes()
或 get_married()
这样的方法,那么第二种方法更合适。
【参考方案1】:
通常您不希望模型有多个经理。最好扩展默认管理器。
class PeopleManager(models.Manager):
def get_male(self):
return self.filter(sex='M')
def get_female(self):
return return self.filter(sex='F')
class Person(models.Model):
....
objects = PeopleManager()
然后您将能够使用Person.objects.get_male()
、Person.objects.get_female()
和Person.objects.order_by()
等内置方法。例如,您可以查看 django.contrib.auth.models
中的自定义管理器。
get_query_set
适合继承。例如你可以定义
class SmithManager(PeopleManager):
def get_queryset(self):
return super(SmithManager, self).get_query_set().filter(last_name='Smith')
并且经理的所有方法将只返回 Smiths,(Person.objects.get_male()
将只返回名为 Smith 的男性,依此类推)。而且你不需要重写所有的方法。
【讨论】:
在这种情况下,在您的第二点中,我想这取决于我如何在模型中实例化对象。如果假设我做对象 = models.Manager() 和 person = SmithManager()。然后,我可以使用默认对象和我继承的自定义对象。 @insane-36 有什么理由不扩展默认管理器?具有多个经理的代码不太清晰且难以维护。好建议:暂时忘记经理。只需使用普通的objects
创建您的视图、表单和其他内容。然后分析使用情况并创建一个优秀的 DRY 管理器来解决您的任务。这将是最好的经理。
谢谢,这个话题很有趣,所以我花了一些时间来回顾一下。我现在就去。以上是关于子类化models.Manager的主要内容,如果未能解决你的问题,请参考以下文章