抽象模型继承(abstract model)
假如我们有如下两个模型Article(文章)和Course(课程)模型。它们的模型中有很多共同的字段,比如作者、标题、创建日期和更新日期
这样写会造成大量的代码重复,一个更好的方式是提取两个模型共同的字段建立一个父类抽象模型(abstract model),再建立子类模型去继承父类。
我们需要根据子类模型的名字,生成差异化的related_name。这时我们只需在父类模型中设置related_name时引用应用名app_label(%(app_label)s)
或者子类的类名(%(class)s)。这里我们使用了%(class)s,表示小写形式的当前子类的类名
这样模型继承后,每个子类模型会生成自己专属的related_name, 比如articles_related和courses_related
class ItemBase(models.Model):
owner = models.ForeignKey(User, related_name='%(class)s_related', on_delete=models.CASCADE)
title = models.CharField(max_length=250)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
多表模型继承(multi-table inheritance)
Django的多表模型也可用来简化代码,其与抽象模型继承最大的区别在于Django也会为父类模型建立自己的数据表
同时隐式地在父类和子类之间建立一个一对一关系。比如下例中,我们删除了父类模型Meta选项中的abstract=True,
这样Django就会创建3个数据表。其中共有字段部分会存储在父类模型对应的数据表里,每个子类模型专属的字段会存在每个子类对应的数据表里
尽管共有字段是存在父类模型对应的数据表里,每个子类对象可以像使用自己数据表里的字段一样使用那些字段,比如article.title, course.owner
多表继承中如果一个父类有多个子类,且子类不在关系中显式地指定related_name字段,django会引发验证错误。
这是因为多表继承的时候,Django隐式地在父类和子类之间建立一个一对一关系,有时候父类与其他类的关系会从父类下移到子类中。
代理模型(proxy model)
有时候你需要给子类代理模型自定义Manager方法,你可以按如下操作。
from django.db import models
class NewManager(models.Manager):
...
pass
class MyPerson(Person):
objects = NewManager()
class Meta:
proxy = True
但上述操作有个问题,其覆盖了父类的操作方法,比如MyPerson.objects.all()
如果你希望保留父类自带方法,同时提供新的Manager方法,可以按如下操作。
class ExtraManagers(models.Model):
secondary = NewManager()
class Meta:
abstract = True
class MyPerson(Person, ExtraManagers):
class Meta:
proxy = True