Django Model Mixins:从models.Model继承还是从object继承?


78

这是一个关于Python Mixins的问题,该问题通常可能有用。我只是使用Django模型,因为这是我最熟悉的用例。

mixin应该从它设计为与“对象”混合的类继承吗?

通过代码示例,哪个更正确或更佳,或更佳,取决于您要实现的目标?

这个

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)

我认为从对象继承是正确的方法。但是我在网上看到第一种情况的例子...

编辑:我已经将我的跟进问题移到一个单独的问题:Django抽象模型与简单的Python mixins与Python ABC

Answers:


82

Django在模型类方面做了大量的魔术工作,因此很遗憾,丹尼尔·罗斯曼(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)

这里的重点是:

  • Mixins继承model.Model但配置为抽象类。
  • 由于混入继承model.Model,您的实际模型应该没有继承它。如果这样做,则可能会触发一致的方法解析顺序异常。

1
这将导致 TypeError: Cannot create a consistent method resolution order (MRO)。做吧class MyModel(TaggingMixin):。参见stackoverflow.com/q/29214888/1627479
Joren

谢谢@Joren。编辑答案以反映这一点。
jsdalton

21
“ Mixin”在这里是一个错误的术语。这只是一个抽象模型。您不能将其与models.Model其他抽象模型“混合”
David Avsajanishvili,

15

我建议它继承自object。这样,您可以确保它仅提供您实际明确定义的那些方法和属性。

另外,在定义具体类时,应始终确保将mixin类放在首位。Python的解析规则意味着在类声明中按其定义的顺序搜索超类,并在找到匹配的属性时停止解析。因此,如果您的mixin定义了也由主超类定义的方法,则不会找到您的mixin方法。


12
如果您的mixin类没有继承自models.Model(或者更具体地说,没有__metaclass__必需的继承),那么添加字段的元类魔术将不起作用。
马修·辛克尔

2
从对象继承对我不起作用。请参阅:stackoverflow.com/questions/17343867/...
utapyngo

2
继承对象不是django的好方法。因为Django makemigrations无法识别它。迁移文件不包含归档的文件。
9nix00年

最好添加一个带有模板的小示例。
Pithikos


3

当您从纯Python对象继承时,South不会创建迁移,因此您无法使用此方法


1
它与南方移民无关。
马修·辛克尔

我的意思是,这种方法不能与南方打得很好,这对我来说是个大问题
kharandziuk
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.