子类化 models.Manager
我觉得在子类中继承 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')
1 个回答
3
通常情况下,你不想为模型创建多个管理器。扩展默认的管理器会更好。
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')
这样管理器的所有方法都会只返回姓氏为 Smith 的人(
Person.objects.get_male()
只会返回名叫 Smith 的男性,依此类推)。而且你不需要重写所有的方法。