Django模型的继承
Django模型的继承,包括模型的抽象基类、Meta继承、related_name和related_query_name属性、多表继承、Meta和多表继承、继承与反向关系、代理模型、代理模型继承和未托管模型,以及多重继承等内容。本文讲解一下抽象基类继承,其他继承后续发布。
3.6.1 关于模型继承
Django模型的继承与普通类的继承基本一致,在Python语言中的工作方式也几乎完全相同,同时也要遵循Django官方文档中关于模型的3点描述(参看3.1.2节)。Django模型继承的基类需要继承自django.db.models.Model。
设计人员在使用模型继承时,只需要决定父类模型是否需要拥有数据表,或者父类模型是否仅作为承载子类中可见的公共信息的载体。
Django模型的继承有以下3种可用的集成风格:
- 建议将父类设计为抽象基类来使用,仅用于作为子类的公共信息的载体,免去在每个子类中将这些代码都重复写一遍。
- 假如要继承一个模型,并且想要每个模型都有对应的数据表,则建议使用多表继承方式。
- 假如只想修改模型的Python级行为,而不是以任何形式修改模型字段,则建议使用代理模型方式。
3.6.2 抽象基类
在Django模型中,抽象基类在将公共信息放入很多模型时会非常有用。
如果要实现一个抽象基类,需要先编写好一个基类,然后在该基类中添加Meta类,并填入属性abstract=True。因为这个基类被设计为抽象基类,模型就不会创建任何数据表了。当这个抽象基类用作其他模型类的基类时,其自有字段会自动添加到子类之中。
关于抽象基类的使用方法,示例代码如下:
【代码3-15】
01 from django.db import models
02
03 class CommonInfo(models.Model):
04 name = models.CharField(max_length=100)
05 age = models.PositiveIntegerField()
06
07 class Meta:
08 abstract = True
09
10 class UserInfo(CommonInfo):
11 home_group = models.CharField(max_length=5)
12 #...
13 pass
【代码分析】
在第03~08行代码中,定义了一个描述通用信息的抽象基类CommonInfo。具体内容说明如下:
- 在第04、05行代码中,定义了name(姓名)和age(年龄)的字段属性。
- 在第07、08行代码中,在Meta类中添加了属性"abstract=True",表明CommonInfo类为抽象基类。
在第10、11行代码中,定义了一个关于用户信息的子类UserInfo。具体内容说明如下:
- 在第10行代码中,定义了子类UserInfo继承自基类CommonInfo。
- 在第11行代码中,定义了一个关于家庭组的字段属性home_group。
子类UserInfo因为继承自基类CommonInfo,所以顺带继承了基类CommonInfo中的name和age属性,这样子类UserInfo就拥有了3个字段属性,即name、age和home_group。
注意: 因为基类CommonInfo是一个抽象基类,所以它不能作为普通的Django模型来使用。也就是说,基类CommonInfo不会生成数据表,也没有管理器,同时也不能被实例化和保存。
在Django模型中,从抽象基类继承来的字段可以被其他字段或值重写,或者使用"None"标识符进行删除。
对设计人员来讲,从抽象基类中继承是一种比较理想的方式。抽象基类继承方式提供了一种在Python级别中提取公共信息的方法,同时仍会在子类模型中创建数据表。
本文节选自《Django 5企业级Web应用开发实战(视频教学版)》,获出版社和作者授权发布。