Django定制模型经理

9-b*_*its 12 django django-models django-managers

我对使用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()
Run Code Online (Sandbox Code Playgroud)

class PersonManager(models.Manager):
    def males(self):
        return super(MaleManager, self).get_query_set().filter(sex='M')

    def females(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 = PersonManager()

Person.people.females() # to get list of females
Person.people.males() # to get a list of males
Run Code Online (Sandbox Code Playgroud)

dan*_*era 12

使用第一种方法,您可以编写:

men = Person.men.all()
Run Code Online (Sandbox Code Playgroud)

要么

peters_men = Person.men.filter(first_name='Peter')
Run Code Online (Sandbox Code Playgroud)

对于第二个方法,get_query_set是从模型"继承",然后返回没有自定义的查询集.我不知道有什么理由放弃你的第二种方法,如果你使用管理界面,你应该检查它是否被支持.

此外,对于第二种方法,您应该更正您的问题.是

class PersonManager(models.Manager):
    def males(self):
        return super(PersonManager, self).get_query_set().filter(sex='M')
Run Code Online (Sandbox Code Playgroud)

阅读django manager doc:"你可以通过覆盖Manager.get_query_set()方法来覆盖Manager的基本QuerySet.get_query_set()应该返回一个具有你需要的属性的QuerySet."

编辑2017小心,get_query_set从djanto 1.7改名为get_queryset.更多信息在修改管理器的初始QuerySet

  • 注意,因为Django 1.7`get_query_set()`已经被重命名为`get_queryset()`(没有第二个下划线). (2认同)