1. Meta和多表继承
在Django模型多表继承中,子类不会继承父类中的Meta类。所有的Meta类属性已被应用至父类,在子类中再次应用则会导致行为冲突。因此,子类模型无法访问父类中的Meta类。
不过也有例外情况,若子类未指定ordering属性或get_latest_by属性,则子类会从父类继承这些属性;而如果父类有排序属性,而设计子类时并不期望有排序属性,则可以显式进行禁止。示例代码如下:
【代码3-22】
01 class ChildModel(ParentModel):
02 #...
03 class Meta:
04 # Remove parent's ordering effect
05 ordering = []
06 #...
07 pass
【代码分析】
在第01~07行代码中,定义了一个子类ChildModel,它继承自父类ParentModel,具体内容说明如下:
- 在第03~05行代码中,定义了子类ChildModel的Meta类。其中,第05行代码定义了一个为空的ordering属性,实现了显式地禁止ordering排序属性的操作。
在Django模型继承中,由于多表继承使用隐式的OneToOneField连接子类和父类,因此直接从父类访问子类是可能的。同时,使用的名字是ForeignKey和ManyToManyField关系的默认值。
但是,如果在继承父类模型的子类中添加了这些关联,则必须指定related_name属性。如果不小心遗漏了,Django框架就会抛出一个合法性错误。
例如,使用【代码3-20】中的Place基类创建另一个子类Restaurant,且包含一个ManyToManyField,示例代码如下:
【代码3-23】
01 class Restaurant(Place):
02 customers = models.ManyToManyField(Place)
03 #...
04 pass
【代码分析】
第01~04行代码中,定义了一个子类Restaurant,它继承自父类Place。其中,在第02行代码中定义了子类与父类的ManyToManyField关系。
注意,由于子类Restaurant中没有定义related_name属性,因此会出现异常。
如果想让【代码3-23】的错误异常不出现,就需要将related_name属性添加进ManyToManyField关系中,示例代码如下:
【代码3-24】
01 class Restaurant(Place):
02 customers = models.ManyToManyField(Place, related_name='provider')
03 #...
04 pass
【代码分析】
第02行代码在定义子类与父类的ManyToManyField关系中,添加了“related_name='provider'”属性。
本文节选自《Django 5企业级Web应用开发实战(视频教学版)》,获出版社和作者授权发布。