【Django】model模型—模型继承

Django中三种继承风格

  • 抽象基类:仅将父类用于子类公共信息的载体,这样的父类永远都不会单独使用。
  • 多表继承:继承了一个模型(可能来源其它应用),且想要每个模型都有对应的数据表。
  • 代理模型:只想修改模型的 Python 级行为,而不是以任何形式修改模型字段。

抽象基类

有很多模型需要公共信息的时候,抽象基类就会有用,比如一个后台管理系统,都需要一些用于审计的字段。

例子:

python 复制代码
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)

关于Meta继承

当一个抽象基类被建立,Django 将所有你在基类中申明的 Meta 内部类以属性的形式提供。若子类未定义自己的 Meta 类,它会继承父类的 Meta。Django 在安装 Meta 属性前,对抽象基类的 Meta 做了一个调整------设置 abstract=False。这意味着抽象基类的子类不会自动地变成抽象类。为了继承一个抽象基类创建另一个抽象基类,你需要在子类上显式地设置 abstract=True。

由于Python继承的工作方式,如果子类从多个抽象基类继承,则默认情况下仅继承第一个列出的类的 Meta 选项。为了从多个抽象类中继承 Meta 选项,必须显式地声明 Meta 继承。

关于对 related_name 和 related_query_name 的使用

若你在 外键 或 多对多字段 使用了 related_name 或 related_query_name,你必须为该字段提供一个 独一无二 的反向名字和查询名字。这在抽象基类中一般会引发问题,因为基类中的字段都被子类继承,且保持了同样的值(包括 related_name 和 related_query_name)。
为了解决此问题,当你在抽象基类中(也只能是在抽象基类中)使用 related_name 和 related_query_name,部分值需要包含 '%(app_label)s' 和 '%(class)s'。

多表继承

Django 支持的第二种模型继承方式是层次结构中的每个模型都是一个单独的模型。每个模型都指向分离的数据表,且可被独立查询和创建,即:多表继承,它是使用隐式的 OneToOneField 连接子类和父类。

例子:

python 复制代码
from django.db import models


class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)


class Restaurant(Place):
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)

关于Meta的多表继承

多表继承情况下,子类不会继承父类的 Meta。所有 Meta 类选项已被应用至父类,在子类中再次应用会导致行为冲突(与抽象基类中应用场景对比,这种情况下,基类并不存在)。
故,子类模型无法访问父类的 Meta 类。不过,有限的几种情况下:若子类未指定 ordering 属性或 get_latest_by 属性,子类会从父类继承这些。

如果父类有排序,而你并不期望子类有排序,你可以显式的禁止它:

python 复制代码
class ChildModel(ParentModel):
    # ...
    class Meta:
        # Remove parent's ordering effect
        ordering = []

代理模型

代理模型继承的目的:为原模型创建一个代理。你可以创建,删除和更新代理模型的实例,所以的数据都会存储的像你使用原模型(未代理的)一样。不同点是你可以修改代理默认的模型排序和默认管理器,而不需要修改原模型。
代理模型就像普通模型一样申明。你需要告诉 Django 这是一个代理模型,通过将 Meta 类的 proxy 属性设置为 True。

例子:

python 复制代码
from django.db import models


class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)


class MyPerson(Person):
    class Meta:
        proxy = True

    def do_something(self):
        # ...
        pass
相关推荐
zuYM4g7Dp32 分钟前
NoSql数据库设计心得
数据库·nosql
睡不醒男孩0308232 小时前
第七篇:揭秘 PostgreSQL 数据库内核级管控:CLup 深度架构设计与高可用底座技术白皮书
数据库·postgresql·clup
cmes_love3 小时前
Level 2逐笔成交历史数据下载方法笔记
数据库·笔记·oracle
swordbob3 小时前
MySQL字符集陷阱:从Oracle迁移踩坑到utf8mb4强制规范
数据库·sql
牛油果子哥q3 小时前
【C++ STL string 】C++ STL string 终极精讲:底层原理、内存机制、全套API、深浅拷贝、易错坑点与工程实战规范
数据库·c++
十五年专注C++开发4 小时前
MySql中各种功能用sql语句实现总结
数据库·sql·mysql
数据库小学妹4 小时前
AI时代数据库怎么选?多模融合、数据统一存储与选型实战指南
数据库·人工智能·经验分享·ai
Albert Edison4 小时前
【Redis】Centos7.9 安装 Redis 5 教程
数据库·redis·缓存
云计算磊哥@4 小时前
运维开发宝典026-MySQL02数据库表操作
运维·数据库·运维开发
小二·4 小时前
Redis 内存溢出(OOM)排查与恢复实战
数据库·redis·bootstrap