Django之抽象基类

  • Django中所有的模型都必须继承django.db.models.Model模型,不管是直接继承也好,还是间接继承也罢。

  • 你唯一需要决定的是,父模型是否是一个独立自主的,同样在数据库中创建数据表的模型,还是一个只用来保存子模型共有内容,并不实际创建数据表的抽象模型。

  • 同Python的继承一样,Django也是可以同时继承两个以上父类的!

Django有三种继承的方式:

- 抽象基类:被用来继承的模型被称为Abstract base classes,将子类共同的数据抽离出来,供子类继承重用,它不会创建实际的数据表:  
- 多表继承:Multi-table inheritance,每一个模型都有自己的数据库表;  
- 代理模型:如果你只想修改模型的Python层面的行为,并不想改动模型的字段,可以使用代理模型。
  • 具体应用
    只需要在模型的Meta类里添加abstract=True元数据项,就可以将一个模型转换为抽象基类。Django不会为这种类创建实际的数据库表,它们也没有管理器,不能被实例化也无法直接保存,它们就是用来被继承的。抽象基类完全就是用来保存子模型们共有的内容部分,达到重用的目的。当它们被继承时,它们的字段会全部复制到子模型中。看下面的例子:
    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模型不能当做一个正常的模型使用,Djiango
不会创建实际的数据库表。
  • 抽象基类的Mate数据
如果子类没有声明自己的Meta类,那么它将继承抽象基类的Meta类。下面的例子则扩展了基类的Meta:
from django.db import models

class CommonInfo(models.Model):
    # ...
    class Meta:
        abstract = True
        ordering = ['name']
    
class Student(CommonInfo):
    # ...
    class Meta(CommonInfo.Meta):
        db_table = 'student_info'
这里有几点要特别说明:

- 抽象基类中有的元数据,子模型没有的话,直接继承;
- 抽象基类中有的元数据,子模型也有的话,直接覆盖;
- 子模型可以额外添加元数据;
- 抽象基类中的abstract=True这个元数据不会被继承。也就是说如果想让一个抽象基类的子模型,同样成为一个抽象基类,那你必须显式的在该子模型的Meta中同样声明一个abstract = True;
- 有一些元数据对抽象基类无效,比如db_table,首先是抽象基类本身不会创建数据表,其次它的所有子类也不会按照这个元数据来设置表名。

推荐阅读更多精彩内容