Django模型继承之Meta继承

在Django模型继承中,当一个抽象基类被设计完成后,它会将该基类中定义的Meta内部类以属性的形式提供给子类。另外,如果子类未定义自己的Meta类,那么它就会默认继承抽象基类的Meta类。

关于Meta类的继承,大致总结如下:

  • 抽象基类中有的元数据属性,如果子模型没有,则子模型直接继承。
  • 抽象基类中有的元数据属性,如果子模型也有,则子模型直接覆盖。
  • 子模型可以额外添加元数据属性。
  • 抽象基类中的abstract=True属性不会被子类继承。
  • 有一些元数据属性(如db_table)对抽象基类是无效的。

首先,子类如果要设置自己的Meta属性,则必须扩展抽象基类的Meta类。示例代码如下:

【代码3-16】

复制代码
01  from django.db import models
02  
03  class CommonInfo(models.Model):
04      # ...
05      class Meta:
06          abstract = True
07          ordering = ['name']
08  
09  class StudentInfo(CommonInfo):
10      # ...
11      class Meta(CommonInfo.Meta):   # 注意这里有个继承关系
12          db_table = 'student_info'
13      #...
14      pass

【代码分析】

在第03~07行代码中,定义了一个描述通用信息的抽象基类CommonInfo,具体内容说明如下:

  • 在第05~07行代码中,在Meta类中添加了属性"abstract=True",表明CommonInfo类为抽象基类。

在第09~14行代码中,定义了一个关于学生信息的子类StudentInfo,具体内容说明如下:

  • 在第11行代码中,定义了自己的Meta类子类,并继承自基类的Meta类CommonInfo.Meta。
  • 在第12行代码中,定义了一个字段属性db_table。注意,该属性就是子类StudentInfo所扩展的属于自己的Meta属性。

如前文所述,元数据属性db_table对抽象基类无效。首先,对于抽象基类本身而言,是不会创建数据表的;其次,所有子类也不会按照这个元数据属性来设置表名。

另外,如果想让一个抽象基类的子类也同样成为一个抽象基类,则必须显式地在该子类的Meta类中同样声明一个"abstract=True"属性。示例代码如下:

【代码3-17】

复制代码
01  from django.db import models
02  
03  class CommonInfo(models.Model):
04      # ...
05      class Meta:
06          abstract = True
07          ordering = ['name']
08  
09  class UserInfo(CommonInfo):
10      # ...
11      class Meta(CommonInfo.Meta):   	# 注意这里有个继承关系
12          abstract = True
13          ordering = ['username']
14  
15  class StudentInfo(UserInfo):
16      # ...
17      class Meta(UserInfo.Meta):   		# 注意这里有个继承关系
18          db_table = 'student_info'
19      #...
20      pass

【代码分析】

在第03~07行代码中,定义了一个描述通用信息的抽象基类CommonInfo,具体内容说明 如下:

  • 在第05~07行代码中,在Meta类中添加了属性"abstract=True",表明CommonInfo类为抽象基类。
  • 在第09~13行代码中,定义了一个继承自抽象基类CommonInfo的用户信息子类UserInfo,具体内容说明如下:
  1. 在第11行代码中,定义了自己的Meta类子类,并继承自基类的Meta类CommonInfo.Meta。
  2. 在第12行代码中,在Meta类中添加了属性"abstract=True",表明子类UserInfo仍为抽象基类。

在第15~20行代码中,定义了一个继承自抽象基类UserInfo的学生信息子类StudentInfo,具体内容说明如下:

  • 在第17行代码中,定义了自己的Meta类子类,并继承自基类的Meta类UserInfo.Meta。
  • 在第18行代码中,定义了一个字段属性db_table。注意,该属性就是子类StudentInfo所扩展的属于自己的Meta属性。

最后,基于Python语法继承的工作机制,如果子类继承了多个抽象基类,则默认情况下仅继承第一个列出基类的Meta选项。如果要从多个抽象基类中继承Meta选项,则必须显式地声明Meta继承。示例代码如下:

【代码3-18】

复制代码
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          ordering = ['name']
10  
11  class Unmanaged(models.Model):
12      class Meta:
13          abstract = True
14          managed = False
15  
16  class StudentInfo(CommonInfo, Unmanaged):
17      home_group = models.CharField(max_length=5)
18  
19      class Meta(CommonInfo.Meta, Unmanaged.Meta):
20          pass
21      #...
22      pass

【代码分析】

在第03~09行代码中,定义了第一个描述通用信息的抽象基类CommonInfo,具体内容说明如下:

  • 在第07~09行代码中,在Meta类中添加了属性"abstract=True",表明CommonInfo类为抽象基类。

在第11~14行代码中,定义了第二个抽象基类Unmanaged。在第12~14行代码中,在Meta类中添加了属性"abstract=True",表明Unmanaged类为抽象基类。

在第16~20行代码中,定义了一个同时继承自抽象基类CommonInfo和Unmanaged的学生信息子类StudentInfo,具体内容说明如下:

  • 在第19行代码中,定义了自己的Meta类子类,并继承自基类的Meta类CommonInfo.Meta和Unmanaged.Meta,该定义方式就是显式地声明Meta类继承。

本文节选自《Django 5企业级Web应用开发实战(视频教学版)》,获出版社和作者授权发布。

相关推荐
jerryinwuhan3 分钟前
机器人模拟器(python)
开发语言·python·机器人
咖啡教室8 分钟前
每日一个计算机小知识:Linux
linux·后端
AhriProGramming11 分钟前
Flask-SQLAlchemy精读-双语精选文章
python·算法·flask
列兵阿甘14 分钟前
知微传感Dkam系列3D相机SDK例程篇:Python获取内外参
python·数码相机·3d
IT_陈寒23 分钟前
Vite 5个隐藏技巧让你的项目构建速度提升50%,第3个太香了!
前端·人工智能·后端
用户40993225021225 分钟前
复杂查询总拖后腿?PostgreSQL多列索引+覆盖索引的神仙技巧你get没?
后端·ai编程·trae
Full Stack Developme38 分钟前
java.net 包详解
java·python·.net
凤山老林1 小时前
排序算法:详解插入排序
java·开发语言·后端·算法·排序算法
低音钢琴1 小时前
【SpringBoot从初学者到专家的成长18】SpringBoot中的数据持久化:JPA与Hibernate的结合
spring boot·后端·hibernate
paopaokaka_luck1 小时前
基于SpringBoot+Vue的社区诊所管理系统(AI问答、webSocket实时聊天、Echarts图形化分析)
vue.js·人工智能·spring boot·后端·websocket