Django模型混入:继承自models.Model还是object?

97 投票
4 回答
38040 浏览
提问于 2025-04-16 01:20

这是一个关于Python中Mixin的提问,可能对大家都有帮助。我这里用Django模型作为例子,因为这是我最熟悉的用法。

Mixin应该继承它要混入的类,还是直接继承'object'呢?

通过代码示例,哪种方式更正确或者更好,或者说根据你想要实现的目标,哪种更合适呢?

这种方式:

class TaggingMixin(models.Model):
    tag = models.ForeignKey(Tag)

    class Meta:
        abstract = True

class MyModel(models.Model, TaggingMixin):
    title = models.CharField(max_length=100)

还是这种:

class TaggingMixin(object):
    tag = models.ForeignKey(Tag)

    class Meta:
        abstract = True

class MyModel(models.Model, TaggingMixin):
    title = models.CharField(max_length=100)

我觉得继承'object'是正确的做法。但是我在网上看到很多例子都是第一种情况……

编辑:我把我的后续问题移到了一个单独的问题上: Django抽象模型 vs 简单Python mixins vs Python ABCs

4 个回答

12

这看起来像是需要用到一个抽象模型的情况。

补充说明:

这些其实不算是混入类。或者说,它们不一定要是混入类。你可以直接从一个抽象模型来创建新的模型。

14

我建议让它继承自 object。这样可以确保它只提供你明确定义的方法和属性。

另外,在定义你的具体类时,应该始终把混入类放在 最前面。因为Python的查找规则是按你在类声明中定义的顺序来查找父类的,一旦找到匹配的属性就会停止查找。所以如果你的混入类定义了一个方法,而这个方法在主父类中也有定义,那么你的混入类的方法就找不到了。

104

Django在处理模型类时会做很多“魔法”,所以通常的混入类(mixins)写法,比如Daniel Roseman提到的那种从object继承的方式,在Django里并不太好用。

正确的混入类结构,参考下面的例子:

class TaggingMixin(models.Model):
    tag = models.ForeignKey(Tag)

    class Meta:
        abstract = True

class MyModel(TaggingMixin):
    title = models.CharField(max_length=100)

这里有几个重要的点:

  • 混入类要从model.Model继承,但要设置成抽象类。
  • 因为混入类是从model.Model继承的,所以你的实际模型类不应该从它继承。如果你这样做,可能会引发一种叫做“方法解析顺序异常”的错误。

撰写回答