Django抽象模型 vs 简单Python混入 vs Python ABCs
这是我在另一个问题中引发的一个问题。
Django提供了一种叫做抽象基类的功能(这和Python中的ABC类不一样),这样你可以创建一个模型(Django的models.Model),然后从这个模型继承,但这个模型在数据库中并不会有实际的表。要实现这个功能,你只需要在模型的Meta类中设置'abstract'属性。
现在的问题是:为什么Django要这样解决这个问题?为什么需要这种特殊的“抽象基类”模型?为什么不直接从对象类继承,做一个模型混合类,然后和现有的模型结合在一起呢?或者这也可以是Python ABC类的一个任务吗?(请注意,我对Python的ABC类不是很熟悉,可能会有一些无知的地方)
2 个回答
其中一个原因是模型中字段的定义方式。
字段是以声明的方式来指定的,就像普通类的属性一样。但是,当这个类被实际创建(实例化)时,这些字段需要变成实例属性,这样每个实例才能拥有自己独立的字段值。这一切是通过元类来管理的。普通的抽象基类是无法做到这一点的。
我会尽量简短,因为这个话题很容易变得冗长:
首先,ABCs(抽象基本类)不适用,因为它们只在Python 2.6中引入,而Django的开发者对支持的Python版本有明确的计划(比如,Python 2.3的支持在1.2版本中才被取消)。
至于对象继承的mixins(混入类),它们在很多方面都不够“Pythonic”,不仅仅是因为可读性降低。Django为Model
对象使用了一个叫ModelBase
的元类,这个元类在初始化时会分析定义的模型属性,并把Model._meta
填充上字段、Meta
选项和其他属性。这样做的好处是可以在两种类型的模型中复用这个框架。这也让Django能够防止抽象模型字段被继承的模型覆盖。
我能想到的理由还有很多,虽然每个理由都不算特别重要,但加起来让当前的实现方式更符合Python的风格。不过,使用对象继承的mixins本身并没有什么错误。