- Django 的所有基类都必须是
django.db.models.Model的子类 - Djang 共有三种继承方式:
(1) 抽象基类:基类不会被单独使用(模型不会用于创建任何数据库表),用于保存子模型的一些公共信息
(2) 多表继承:子类化一个现有模型(可能完全来自另一个应用程序),但每个模型都有自己的数据库表
(3) 代理模型:仅修改模型的Python级行为,而不以任何方式更改模型字段
抽象基类
抽象基类声明:像普通模型一样声明,但需要在Meta类中设置abstract=True
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
# 声明抽象基类
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
当进行数据库迁移的时候,由于CommonInfo类声明是抽象基类,所以不会生成数据库表或具有管理器,并且无法直接实例化或保存。
由于 Student 类继承 CommonInfo 类,所以 Student 生成的数据库为Student(name, age, home_group )
Meta 继承
- 当使用抽象基类时,如果子类没有声明它自己的Meta类,它将继承父类的Meta。
- 如果子类想要扩展父类的Meta类,可以将其子类化。
- 当子类继承父类Meta时,会自动设置
abstract=False,即抽象基类的子项本身不会自动成为抽象类,如果想声明抽象基类,必须在自己的Meta中声明abstract=True
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
# 声明抽象基类
class Meta:
abstract = True
ordering = ['name']
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
# 继承CommonInfo类的Meta
class Meta(CommonInfo.Meta):
db_table = 'student_info'
- 在抽象基类Meta类中包含一些属性是无意义的,比如说如果在抽象基类中包含
db_table则意味着所有子类将使用相同的数据库表
多表继承
每个模型对应于自己的数据库表,可以单独查询和创建。多表继承使得子模型与父模型之间创建一对一关系OneToOneField
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
其中Restaurant类等价于
class Restaurant(models.Model):
place_ptr = models.OneToOneField(
Place,
on_delete=models.CASCADE,
parent_link=True,
)
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
Meta与多表继承
- 一般情况下,子类无法继承父类Meta
- 在少数有限的情况下,子类从父类继承行为:如果子类没有指定
ordering属性或get_latest_by属性,那么它将从父元素继承这些属性。 - 如果父级有一个排序,并且您不希望子级具有该排序,则可以使用如
ordering = []明确禁用父类属性
代理模型
- 作用:为原始模型创建代理。代理可以创建、删除和更新代理模型的实例,所有数据都将像使用原始(非代理)模型一样保存。不同之处在于,代理可以更改诸如代理中的默认模型排序或默认管理器之类的内容,而无需更改原始的排序。
- 代理模型声明:像普通模型一样声明,但需要在Meta类中设置
proxy=True
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class MyPerson(Person):
class Meta:
proxy = True
def do_something(self):
# ...
pass
- 代理的意义:仅修改模型的Python级行为,而不以任何方式更改模型字段