Django:如何在Django中实现类的层次结构?

时间:2017-02-05 07:32:28

标签: python django abstract-class

我完全了解MVC框架以及Django如何实现模型和视图。我想知道如何实现自定义Hierarchy类,然后在Django中使用它们。例如:

有一个抽象类Employee,然后是子类; Permanent EmployeeInterns等。员工可以被公司雇佣和解雇。

2 个答案:

答案 0 :(得分:3)

Django中的模型继承几乎与普通类继承在Python中的工作方式相同,但仍应遵循页面开头的基础知识。这意味着基类应该是django.db.models.Model的子类。

您必须做出的唯一决定是,您是希望父模型本身是模型(使用自己的数据库表),还是父母只是通过孩子只能看到的公共信息的持有者模型。

Django中有三种可能的继承方式。

1)

通常,您只想使用父类来保存您不希望为每个子模型键入的信息。这个类不会被孤立地使用,所以抽象基类就是你所追求的。

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)

编辑:

Abstract base classes

当您想要将一些公共信息放入许多其他模型时,抽象基类非常有用。编写基类并将abstract=True放在Meta类中。然后,此模型不会用于创建任何数据库表。相反,当它用作其他模型的基类时,其字段将添加到子类的字段中。在抽象基类中使用与子项中的字段相同的字段是错误的(而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模型将包含三个字段:nameagehome_group。 CommonInfo模型不能用作普通的Django模型,因为它是一个抽象基类。它不会生成数据库表或具有管理器,也无法直接实例化或保存。

对于许多用途,这种类型的模型继承将完全符合您的要求。它提供了一种在Python级别分解公共信息的方法,同时仍然只在数据库级别为每个子模型创建一个数据库表。

2)

如果你是现有模型的子类(可能是完全来自另一个应用程序的东西),并希望每个模型都有自己的数据库表,那么多表继承是可行的方法。

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'

3)

最后,如果您只想修改模型的Python级行为,而不以任何方式更改模型字段,则可以使用代理模型。

from django.db import models

class Base(models.Model):
    m2m = models.ManyToManyField(
        OtherModel,
        related_name="%(app_label)s_%(class)s_related",
        related_query_name="%(app_label)s_%(class)ss",
    )

    class Meta:
        abstract = True

class ChildA(Base):
    pass

class ChildB(Base):
    pass

与另一个app rare / models.py一起使用:

from common.models import Base

class ChildB(Base):
    pass

有关详细信息,您可能需要继续阅读文档here

有一个维护良好的项目,名为django-mptt,它使用Django模型实现Modified Preorder Tree Traversal并使用Model实例树。

答案 1 :(得分:0)

如果我理解你,你有两个类层次结构。您可以使用桥接模式来处理它。您的自定义层次结构可以被视为抽象,Django部分可以被视为实现。桥模式也可以被认为是两层抽象。

  

桥接模式是软件工程中使用的设计模式   这意味着“将抽象与其实现分离出去   这两者可以独立变化“,由四人组介绍   (GOF)。网桥使用封装,聚合,并且可以使用   继承将职责分成不同的类。   https://en.wikipedia.org/wiki/Bridge_pattern