Loading django/db/migrations/writer.py +1 −1 Original line number Diff line number Diff line Loading @@ -194,7 +194,7 @@ class MigrationWriter(object): if isinstance(value, set): format = "set([%s])" elif isinstance(value, tuple): format = "(%s)" if len(value) else "(%s,)" format = "(%s)" if len(value) > 1 else "(%s,)" else: format = "[%s]" return format % (", ".join(strings)), imports Loading django/db/models/base.py +4 −1 Original line number Diff line number Diff line Loading @@ -251,6 +251,9 @@ class ModelBase(type): attr_name = '%s_ptr' % base._meta.model_name field = OneToOneField(base, name=attr_name, auto_created=True, parent_link=True) # Only add the ptr field if it's not already present; # e.g. migrations will already have it specified if not hasattr(new_class, attr_name): new_class.add_to_class(attr_name, field) else: field = None Loading tests/migrations/test_operations.py +32 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,38 @@ class OperationTests(MigrationTestBase): self.assertEqual(len(definition[2]), 0) self.assertEqual(definition[1][0], "Pony") def test_create_model_inheritance(self): """ Tests the CreateModel operation on a multi-table inheritance setup. """ project_state = self.set_up_test_model("test_crmoih") # Test the state alteration operation = migrations.CreateModel( "ShetlandPony", [ ('pony_ptr', models.OneToOneField( auto_created=True, primary_key=True, to_field=u'id', serialize=False, to='test_crmoih.Pony', )), ("cuteness", models.IntegerField(default=1)), ], ) new_state = project_state.clone() operation.state_forwards("test_crmoih", new_state) self.assertIn(("test_crmoih", "shetlandpony"), new_state.models) # Test the database alteration self.assertTableNotExists("test_crmoih_shetlandpony") with connection.schema_editor() as editor: operation.database_forwards("test_crmoih", editor, project_state, new_state) self.assertTableExists("test_crmoih_shetlandpony") # And test reversal with connection.schema_editor() as editor: operation.database_backwards("test_crmoih", editor, new_state, project_state) self.assertTableNotExists("test_crmoih_shetlandpony") def test_delete_model(self): """ Tests the DeleteModel operation. Loading tests/migrations/test_state.py +30 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,12 @@ class StateTests(TestCase): proxy = True ordering = ["name"] class SubAuthor(Author): width = models.FloatField(null=True) class Meta: app_label = "migrations" apps = new_apps class Book(models.Model): title = models.CharField(max_length=1000) author = models.ForeignKey(Author) Loading @@ -47,6 +53,7 @@ class StateTests(TestCase): project_state = ProjectState.from_apps(new_apps) author_state = project_state.models['migrations', 'author'] author_proxy_state = project_state.models['migrations', 'authorproxy'] sub_author_state = project_state.models['migrations', 'subauthor'] book_state = project_state.models['migrations', 'book'] self.assertEqual(author_state.app_label, "migrations") Loading @@ -55,7 +62,7 @@ class StateTests(TestCase): self.assertEqual(author_state.fields[1][1].max_length, 255) self.assertEqual(author_state.fields[2][1].null, False) self.assertEqual(author_state.fields[3][1].null, True) self.assertEqual(author_state.options, {"unique_together": {("name", "bio")}}) self.assertEqual(author_state.options, {"unique_together": set([("name", "bio")])}) self.assertEqual(author_state.bases, (models.Model, )) self.assertEqual(book_state.app_label, "migrations") Loading @@ -73,6 +80,11 @@ class StateTests(TestCase): self.assertEqual(author_proxy_state.options, {"proxy": True, "ordering": ["name"]}) self.assertEqual(author_proxy_state.bases, ("migrations.author", )) self.assertEqual(sub_author_state.app_label, "migrations") self.assertEqual(sub_author_state.name, "SubAuthor") self.assertEqual(len(sub_author_state.fields), 2) self.assertEqual(sub_author_state.bases, ("migrations.author", )) def test_render(self): """ Tests rendering a ProjectState into an Apps. Loading @@ -89,10 +101,27 @@ class StateTests(TestCase): {}, None, )) project_state.add_model_state(ModelState( "migrations", "SubTag", [ ('tag_ptr', models.OneToOneField( auto_created=True, primary_key=True, to_field=u'id', serialize=False, to='migrations.Tag', )), ("awesome", models.BooleanField()), ], options={}, bases=("migrations.Tag",), )) new_apps = project_state.render() self.assertEqual(new_apps.get_model("migrations", "Tag")._meta.get_field_by_name("name")[0].max_length, 100) self.assertEqual(new_apps.get_model("migrations", "Tag")._meta.get_field_by_name("hidden")[0].null, False) self.assertEqual(len(new_apps.get_model("migrations", "SubTag")._meta.local_fields), 2) def test_render_model_inheritance(self): class Book(models.Model): Loading Loading
django/db/migrations/writer.py +1 −1 Original line number Diff line number Diff line Loading @@ -194,7 +194,7 @@ class MigrationWriter(object): if isinstance(value, set): format = "set([%s])" elif isinstance(value, tuple): format = "(%s)" if len(value) else "(%s,)" format = "(%s)" if len(value) > 1 else "(%s,)" else: format = "[%s]" return format % (", ".join(strings)), imports Loading
django/db/models/base.py +4 −1 Original line number Diff line number Diff line Loading @@ -251,6 +251,9 @@ class ModelBase(type): attr_name = '%s_ptr' % base._meta.model_name field = OneToOneField(base, name=attr_name, auto_created=True, parent_link=True) # Only add the ptr field if it's not already present; # e.g. migrations will already have it specified if not hasattr(new_class, attr_name): new_class.add_to_class(attr_name, field) else: field = None Loading
tests/migrations/test_operations.py +32 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,38 @@ class OperationTests(MigrationTestBase): self.assertEqual(len(definition[2]), 0) self.assertEqual(definition[1][0], "Pony") def test_create_model_inheritance(self): """ Tests the CreateModel operation on a multi-table inheritance setup. """ project_state = self.set_up_test_model("test_crmoih") # Test the state alteration operation = migrations.CreateModel( "ShetlandPony", [ ('pony_ptr', models.OneToOneField( auto_created=True, primary_key=True, to_field=u'id', serialize=False, to='test_crmoih.Pony', )), ("cuteness", models.IntegerField(default=1)), ], ) new_state = project_state.clone() operation.state_forwards("test_crmoih", new_state) self.assertIn(("test_crmoih", "shetlandpony"), new_state.models) # Test the database alteration self.assertTableNotExists("test_crmoih_shetlandpony") with connection.schema_editor() as editor: operation.database_forwards("test_crmoih", editor, project_state, new_state) self.assertTableExists("test_crmoih_shetlandpony") # And test reversal with connection.schema_editor() as editor: operation.database_backwards("test_crmoih", editor, new_state, project_state) self.assertTableNotExists("test_crmoih_shetlandpony") def test_delete_model(self): """ Tests the DeleteModel operation. Loading
tests/migrations/test_state.py +30 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,12 @@ class StateTests(TestCase): proxy = True ordering = ["name"] class SubAuthor(Author): width = models.FloatField(null=True) class Meta: app_label = "migrations" apps = new_apps class Book(models.Model): title = models.CharField(max_length=1000) author = models.ForeignKey(Author) Loading @@ -47,6 +53,7 @@ class StateTests(TestCase): project_state = ProjectState.from_apps(new_apps) author_state = project_state.models['migrations', 'author'] author_proxy_state = project_state.models['migrations', 'authorproxy'] sub_author_state = project_state.models['migrations', 'subauthor'] book_state = project_state.models['migrations', 'book'] self.assertEqual(author_state.app_label, "migrations") Loading @@ -55,7 +62,7 @@ class StateTests(TestCase): self.assertEqual(author_state.fields[1][1].max_length, 255) self.assertEqual(author_state.fields[2][1].null, False) self.assertEqual(author_state.fields[3][1].null, True) self.assertEqual(author_state.options, {"unique_together": {("name", "bio")}}) self.assertEqual(author_state.options, {"unique_together": set([("name", "bio")])}) self.assertEqual(author_state.bases, (models.Model, )) self.assertEqual(book_state.app_label, "migrations") Loading @@ -73,6 +80,11 @@ class StateTests(TestCase): self.assertEqual(author_proxy_state.options, {"proxy": True, "ordering": ["name"]}) self.assertEqual(author_proxy_state.bases, ("migrations.author", )) self.assertEqual(sub_author_state.app_label, "migrations") self.assertEqual(sub_author_state.name, "SubAuthor") self.assertEqual(len(sub_author_state.fields), 2) self.assertEqual(sub_author_state.bases, ("migrations.author", )) def test_render(self): """ Tests rendering a ProjectState into an Apps. Loading @@ -89,10 +101,27 @@ class StateTests(TestCase): {}, None, )) project_state.add_model_state(ModelState( "migrations", "SubTag", [ ('tag_ptr', models.OneToOneField( auto_created=True, primary_key=True, to_field=u'id', serialize=False, to='migrations.Tag', )), ("awesome", models.BooleanField()), ], options={}, bases=("migrations.Tag",), )) new_apps = project_state.render() self.assertEqual(new_apps.get_model("migrations", "Tag")._meta.get_field_by_name("name")[0].max_length, 100) self.assertEqual(new_apps.get_model("migrations", "Tag")._meta.get_field_by_name("hidden")[0].null, False) self.assertEqual(len(new_apps.get_model("migrations", "SubTag")._meta.local_fields), 2) def test_render_model_inheritance(self): class Book(models.Model): Loading