diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py index 49a29e5b37..ed3fb07d86 100644 --- a/django/db/backends/base/schema.py +++ b/django/db/backends/base/schema.py @@ -578,6 +578,8 @@ class BaseDatabaseSchemaEditor: old_default = self.effective_default(old_field) new_default = self.effective_default(new_field) needs_database_default = ( + old_field.null and + not new_field.null and old_default != new_default and new_default is not None and not self.skip_default(new_field) diff --git a/tests/schema/tests.py b/tests/schema/tests.py index abcaa5b480..833611df3a 100644 --- a/tests/schema/tests.py +++ b/tests/schema/tests.py @@ -1956,6 +1956,21 @@ class SchemaTests(TransactionTestCase): if connection.features.can_introspect_default: self.assertIsNone(field.default) + @unittest.skipIf(connection.vendor == 'sqlite', 'SQLite naively remakes the table on field alteration.') + def test_alter_field_default_doesnt_perfom_queries(self): + """ + No queries are performed if a field default changes and the field's + not changing from null to non-null. + """ + with connection.schema_editor() as editor: + editor.create_model(AuthorWithDefaultHeight) + old_field = AuthorWithDefaultHeight._meta.get_field('height') + new_default = old_field.default * 2 + new_field = PositiveIntegerField(null=True, blank=True, default=new_default) + new_field.set_attributes_from_name('height') + with connection.schema_editor() as editor, self.assertNumQueries(0): + editor.alter_field(AuthorWithDefaultHeight, old_field, new_field, strict=True) + def test_add_textfield_unhashable_default(self): # Create the table with connection.schema_editor() as editor: