子类化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的主要内容,如果未能解决你的问题,请参考以下文章

CAsyncSocket 没有子类化?

子类化导航控制器有啥用? [关闭]

麻烦子类化 SCNScene

UIViewController 的 Swift 子类化子类

子类化 UIAlertController

子类化 UItableViewCell 选择