summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2014-03-04 12:33:51 -0800
committerAndrew Godwin <andrew@aeracode.org>2014-03-04 12:33:51 -0800
commit8fcc0140d075688e7b0565dea225f4380fc638c4 (patch)
tree40de7653b1fa36deb51d44d937376b2eb0984478 /django
parent6fe22b30e007b7ac49eae48a53e7ba0a4ee79a4b (diff)
parent6436f1fad9ce51f18735106ac75aeea3d6d1f310 (diff)
Merge pull request #2396 from loic/ticket21893
Fixed #21893 -- ModelState didn't account for MTI parents inherited from abstract models.
Diffstat (limited to 'django')
-rw-r--r--django/db/migrations/state.py22
1 files changed, 19 insertions, 3 deletions
diff --git a/django/db/migrations/state.py b/django/db/migrations/state.py
index 76fc42d368..90226221be 100644
--- a/django/db/migrations/state.py
+++ b/django/db/migrations/state.py
@@ -151,6 +151,23 @@ class ModelState(object):
options[name] = set(normalize_together(it))
else:
options[name] = model._meta.original_attrs[name]
+
+ def flatten_bases(model):
+ bases = []
+ for base in model.__bases__:
+ if hasattr(base, "_meta") and base._meta.abstract:
+ bases.extend(flatten_bases(base))
+ else:
+ bases.append(base)
+ return bases
+
+ # We can't rely on __mro__ directly because we only want to flatten
+ # abstract models and not the whole tree. However by recursing on
+ # __bases__ we may end up with duplicates and ordering issues, we
+ # therefore discard any duplicates and reorder the bases according
+ # to their index in the MRO.
+ flattened_bases = sorted(set(flatten_bases(model)), key=lambda x:model.__mro__.index(x))
+
# Make our record
bases = tuple(
(
@@ -158,12 +175,11 @@ class ModelState(object):
if hasattr(base, "_meta") else
base
)
- for base in model.__bases__
- if (not hasattr(base, "_meta") or not base._meta.abstract)
+ for base in flattened_bases
)
# Ensure at least one base inherits from models.Model
if not any((isinstance(base, six.string_types) or issubclass(base, models.Model)) for base in bases):
- bases = (models.Model, )
+ bases = (models.Model,)
return cls(
model._meta.app_label,
model._meta.object_name,