Loading django/db/migrations/state.py +19 −3 Original line number Diff line number Diff line Loading @@ -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( ( Loading @@ -158,8 +175,7 @@ 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): Loading tests/migrations/test_state.py +15 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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): """ Loading Loading
django/db/migrations/state.py +19 −3 Original line number Diff line number Diff line Loading @@ -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( ( Loading @@ -158,8 +175,7 @@ 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): Loading
tests/migrations/test_state.py +15 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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): """ Loading