Kaydet (Commit) 6436f1fa authored tarafından Loic Bistuer's avatar Loic Bistuer

Fixed #21893 -- ModelState didn't account for MTI parents inherited from abstract models.

üst 99291f5d
......@@ -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,
......
......@@ -166,6 +166,16 @@ class StateTests(TestCase):
app_label = "migrations"
apps = Apps()
class AbstractSubFooBar(FooBar):
class Meta:
abstract = True
apps = Apps()
class SubFooBar(AbstractSubFooBar):
class Meta:
app_label = "migrations"
apps = Apps()
apps = Apps(["migrations"])
# We shouldn't be able to render yet
......@@ -175,8 +185,13 @@ class StateTests(TestCase):
# Once the parent models are in the app registry, it should be fine
ModelState.from_model(Foo).render(apps)
self.assertSequenceEqual(ModelState.from_model(Foo).bases, [models.Model])
ModelState.from_model(Bar).render(apps)
self.assertSequenceEqual(ModelState.from_model(Bar).bases, [models.Model])
ModelState.from_model(FooBar).render(apps)
self.assertSequenceEqual(ModelState.from_model(FooBar).bases, ['migrations.foo', 'migrations.bar'])
ModelState.from_model(SubFooBar).render(apps)
self.assertSequenceEqual(ModelState.from_model(SubFooBar).bases, ['migrations.foobar'])
def test_render_project_dependencies(self):
"""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment