djangodjango-modelsmultiple-inheritanceabstract-base-class

Django field clash with multiple abstract base clases


I am trying to define entity architecture that, if simplified, can be expressed like this:

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

As you can see, X has some mixins (abstract entitites). Each of the mixin has their own custom logic implemented inside them. But ultimately all of them have 1 common parent- abstract class A.

As far as I understand, this should work. And MRO resolution, indeed, works. However, when starting the project I get 2 errors per each field field A (that are inherited in X):

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'.

I am working with Django 1.11


Solution

  • There is an old issue ticket here that resulted in making Django validate these kinds of problems https://code.djangoproject.com/ticket/24542

    It is because B and C inherit from A so they will have the same field_m and it is not valid. Django devs decided that Django will validate this instead of

    ignore subsequent model fields from abstract model base classes (per MRO-order) with the same name as existing fields.

    On a side note. This is bad design and you should keep your inheritance simple as per the docs https://docs.djangoproject.com/en/2.2/topics/db/models/#s-multiple-inheritance

    Generally, you won’t need to inherit from multiple parents. The main use-case where this is useful is for “mix-in” classes: adding a particular extra field or method to every class that inherits the mix-in. Try to keep your inheritance hierarchies as simple and straightforward as possible so that you won’t have to struggle to work out where a particular piece of information is coming from.