Django 抽象模型 vs 简单的 Python 混入 vs Python ABCs

13

这是由我另一个问题引发的问题。

Django提供了抽象基类功能(它们与Python中的ABC类不同?),使得我们可以创建一个模型(Django的models.Model)作为父类,让其他模型从中继承,但是并不会在数据库中生成该模型的表格。通过在Model的Meta类中设置 'abstract' 属性来启用此行为。

现在的问题是:Django为什么要这样解决呢?为什么需要这种特殊类型的“抽象基类”模型?为什么不通过从object类继承并将其混合到现有模型中来创建模型mixin?或者这也可以使用Python ABCs完成吗?(请注意,我对Python中的ABC类不太熟悉,可能会表现出我的无知)

2个回答

14

我将尽量简要,因为这很容易变成一篇冗长的讲话:

ABC由于只在Python 2.6中引入,而Django开发人员有一套Python版本支持的路线图(1.2版仅取消了对2.3的支持),所以它们已经过时了。

至于继承自对象的混合类,它们会在多个方面降低可读性,也不太符合Pythonic的风格。 Django使用ModelBase元类来处理Model对象,该元类实际上会分析初始值定义的模型属性,并用字段、选项和其他属性填充Model._meta。重复使用此框架可以对两种类型的模型进行重用。这还使得Django能够防止被继承模型覆盖抽象模型字段。

我可以想到更多原因,虽然它们都很小,但加起来使当前实现更符合Pythonic风格。但是,使用继承自对象的混合类本身并没有任何本质的错误。


我理解正确吗?通过使用对象继承的mixin,我可以在模型上声明额外的字段?但是我也可以添加额外的方法或覆盖它们? - hopla
是的,对象继承混合可以声明额外的字段和方法。您可以通过确保您的对象继承混合出现在要继承的类列表中的第一位来覆盖方法。但是,无论顺序如何,对象继承混合都不能覆盖字段(如果尝试覆盖字段,它不会验证失败)。 - Aram Dulyan

8

其中一个原因是由于模型上定义字段的方式。

字段以声明方式指定,这是正常类将其视为类属性的方式。但是,当实际实例化类时,它们需要成为实例属性,以便每个实例可以为每个字段具有自己的值。这是通过元类来管理的。这在普通的抽象基类中无法实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接