#24542 closed Bug (fixed)
Inheriting from multiple abstract model base classes with the same field leads to invalid SQL and db-level exception
Reported by: | Ien Cheng | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.6 |
Severity: | Normal | Keywords: | multiple model inheritance sql fielderror |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Given the following model classes:
class Daddy(models.Model): class Meta: abstract = True foobar = models.CharField(default="", max_length=20) class Mommy(models.Model): class Meta: abstract = True foobar = models.CharField(default="", max_length=20) class Kid(Daddy, Mommy): pass
Django will validate this. However, the foobar field will show up twice in Kid._meta.local_fields, and if you try to save a Kid model instance, Django will generate SQL code that references foobar twice, leading to a hard-to-debug database level exception.
I suggest expected behavior to be either (1) throw a FieldError on validation (consistent with what Django does if a child model tries to "hide" a parent's field) or (2) ignore subsequent model fields from abstract model base classes (per MRO-order) with the same name as existing fields.
The real-world context that led to this bug discovery: in refactoring a large existing project, I subclassed models.Model and had all project models inherit from this subclass, which added a new field (let's call it foobar). Some models had multiple abstract base classes that subclassed from models.Model, in a typical mixin pattern. Django was validating and then creating foobar twice for such models, leading to the database error due to invalid SQL.
It's been fixed in Django 1.7 with the following validation error: polls.Kid.foobar: (models.E006) The field 'foobar' clashes with the field 'foobar' from model 'polls.kid'.