django

模型继承之抽象基类

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

例:

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。
上一篇下一篇

猜你喜欢

热点阅读