【问题标题】:Django field clash with multiple abstract base clases具有多个抽象基类的 Django 字段类
【发布时间】:2019-12-26 11:22:42
【问题描述】:

我正在尝试定义实体架构,如果简化的话,可以这样表达:

class M(models.Model):
    field_m = models.CharField(max_length=255)
    class Meta:
        abstract = True

class A(M):
    field_a_1 = models.CharField(max_length=255)
    field_a_2 = models.CharField(max_length=255)
    class Meta:
        abstract = True

class B(A):
    field_b = models.CharField(max_length=255)
    class Meta:
        abstract = True

class C(A):
    field_c = models.CharField(max_length=255)
    class Meta:
        abstract = True


class D(A):
    field_d = models.CharField(max_length=255)
    class Meta:
        abstract = True

class DD(D):
    class Meta:
        abstract = True

class X(B, C, DD):
    field_x = models.CharField(max_length=255)
    pass

如您所见,X 有一些混入(抽象实体)。每个 mixin 都在其中实现了自己的自定义逻辑。但最终他们都有一个共同的父摘要class A

据我了解,这应该可行。 MRO 解决方案确实有效。但是,在启动项目时,每个字段字段 A(在 X 中继承)出现 2 个错误:

X.field_m : (models.E006) The field 'field_m ' clashes with the field 'field_m ' from model 'X'.
X.field_m : (models.E006) The field 'field_m ' clashes with the field 'field_m ' from model 'X'.
X.field_a_1 : (models.E006) The field 'field_a_1 ' clashes with the field 'field_a_1 ' from model 'X'.
X.field_a_1 : (models.E006) The field 'field_a_1 ' clashes with the field 'field_a_1 ' from model 'X'.
X.field_a_2 : (models.E006) The field 'field_a_2 ' clashes with the field 'field_a_2 ' from model 'X'.
X.field_a_2 : (models.E006) The field 'field_a_2 ' clashes with the field 'field_a_2 ' from model 'X'.

我正在使用 Django 1.11

【问题讨论】:

  • 您没有在X 上定义字段,或与名称为field_a_1X 建立关系?
  • @WillemVanOnsem 否(再次检查以防万一)。每个类都有自己的自定义字段,但它们从不重复。
  • @WillemVanOnsem 我编辑了代码和输出部分以提供更多细节。

标签: django django-models multiple-inheritance abstract-base-class


【解决方案1】:

这里有一个旧问题单,导致 Django 验证这些类型的问题 https://code.djangoproject.com/ticket/24542

这是因为 B 和 C 从 A 继承,所以它们将具有相同的 field_m 并且它是无效的。 Django 开发人员决定 Django 将验证这一点而不是

忽略与现有字段同名的抽象模型基类(按 MRO 订单)中的后续模型字段。

附带说明。这是一个糟糕的设计,您应该按照文档https://docs.djangoproject.com/en/2.2/topics/db/models/#s-multiple-inheritance

保持简单的继承

通常,您不需要从多个父母那里继承。这很有用的主要用例是“混入”类:向每个继承混入的类添加特定的额外字段或方法。尽量让您的继承层次结构尽可能简单明了,这样您就不必费力找出特定信息的来源。

【讨论】:

  • 我想知道这是否是糟糕的设计。例如,我有一个表示人类可读 id 的“数字”字段。例如,我想将它用于从 A 继承的每个 mixin 类中的日志记录和异常消息。我应该如何设计它?我曾经为同名的类添加属性,但这似乎是一个更糟糕的设计。此外,这在 python 中是可能的,只有 Django 限制它并声明它是一个糟糕的设计,所以我仍然不确定。但我明白了,框架不允许这样做,所以我应该以不同的方式设计它。
  • 是的,我不能说为什么 Django 开发人员决定不允许这样做,但是阅读了这个问题,这是因为后来 Django 尝试将同一字段两次保存到数据库中,导致难以理解的错误信息。我认为更容易验证它是不允许的,而不是忽略后续的模型字段。至于身份证部分。您应该添加一个名为 LoggingID 的单独抽象类,并在其中包含该 id 字段。而不是继承 LoggingID 到另一个抽象类你做class RealModel(AbstractClass, AnotherAbstractClass, LoggingID)
  • 只要确保AbstractClassAnotherAbstractClass 不继承自LoggingID 或具有与LoggingID 冲突的字段。但是再次尝试保持简单,我只是做了那个例子,所以我的意思很清楚:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-05
  • 2016-06-10
  • 2016-09-11
  • 2011-06-18
  • 2012-09-21
  • 2016-04-15
  • 1970-01-01
相关资源
最近更新 更多