模型继承之抽象基类
2018-08-23 本文已影响62人
陆_志东
抽象基类的原因:
当你想将一些共有信息放进其它一些model的时候,抽象化类是十分有用的。
当你编写完模型类之后,在Meta类中设置abstract=True ,这个模型就不会被用来创建任何数据表.
取而代之的是,当它被用来作为一个其他model的基类时,它的字段将被加入那些子类中。如果抽象基类和它的子类有相同的字段名,那么将会出现error
示例:
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)
#Student 模型将有三个项:name, age 和 home_group。CommonInfo 模型无法像一般的Django模型一样使用,因为它是一个抽象基类。
#它无法生成一张数据表或者拥有一个管理器,并且不能实例化或者直接储存。
#许多应用场景下, 这种类型的模型继承恰好是你想要的。
#它提供一种在 Python 语言层级上提取公共信息的方式,同时在数据库层级上,每个子类各自仍然只创建一个数据库表。
抽象基类的时候一定要小心related_name
反向引用
因为Django 会将基类字段添加到每个子类当中,而每个子类的字段属性值都完全相同 (这里面就包括related_name
)。
解决办法:添加related_name
字段值的时候加上%(app_label)s
或 %(class)s
- '%(class)s' 会替换为子类的小写加下划线格式的名称,字段在子类中使用。
- '%(app_label)s' 会替换为应用的小写加下划线格式的名称,应用包含子类。每个安装的应用名称都应该是唯一的,而且应用里每个模型类的名称也应该是唯一的,所以产生的名称应该彼此不同。
例:
from django.db import models
class Base(models.Model):
m2m = models.ManyToManyField(OtherModel, related_name="%(app_label)s_%(class)s_related")
class Meta:
abstract = True
class ChildA(Base): # ChildA.m2m 字段的反向名称是 common_childa_related,
pass
class ChildB(Base): # ChildB.m2m 字段的反向名称是 rare_childb_related。
pass
如果你没有在抽象基类中为某个关联字段定义related_name 属性,
那么默认的反向名称就是子类名称加上'_set',它能否正常工作取决于你是否在子类中定义了同名字段。
在上面的代码中,如果去掉 related_name 字段 ,在ChildA中,m2m 字段的反向名称就是的反向名称就是childa_set,
而 ChildB的 m2m 字段的反向名称就是 childb_set。