Fixed #25253 -- Made AlterField operation a noop when changing attributes that don't affect the schema.

This commit is contained in:
Çağıl Uluşahin 2020-10-04 13:24:20 +01:00 committed by Mariusz Felisiak
parent 68e33b347d
commit 9159d173c3
2 changed files with 47 additions and 2 deletions

View File

@ -1063,9 +1063,25 @@ class BaseDatabaseSchemaEditor:
_, new_path, new_args, new_kwargs = new_field.deconstruct() _, new_path, new_args, new_kwargs = new_field.deconstruct()
# Don't alter when: # Don't alter when:
# - changing only a field name # - changing only a field name
# - changing an attribute that doesn't affect the schema
# - adding only a db_column and the column name is not changed # - adding only a db_column and the column name is not changed
old_kwargs.pop('db_column', None) non_database_attrs = [
new_kwargs.pop('db_column', None) 'blank',
'db_column',
'editable',
'error_messages',
'help_text',
'limit_choices_to',
# Database-level options are not supported, see #21961.
'on_delete',
'related_name',
'related_query_name',
'validators',
'verbose_name',
]
for attr in non_database_attrs:
old_kwargs.pop(attr, None)
new_kwargs.pop(attr, None)
return ( return (
self.quote_name(old_field.column) != self.quote_name(new_field.column) or self.quote_name(old_field.column) != self.quote_name(new_field.column) or
(old_path, old_args, old_kwargs) != (new_path, new_args, new_kwargs) (old_path, old_args, old_kwargs) != (new_path, new_args, new_kwargs)

View File

@ -2758,6 +2758,35 @@ class SchemaTests(TransactionTestCase):
with connection.schema_editor() as editor, self.assertNumQueries(0): with connection.schema_editor() as editor, self.assertNumQueries(0):
editor.alter_field(AuthorWithDefaultHeight, old_field, new_field, strict=True) editor.alter_field(AuthorWithDefaultHeight, old_field, new_field, strict=True)
@skipUnlessDBFeature('supports_foreign_keys')
def test_alter_field_fk_attributes_noop(self):
"""
No queries are performed when changing field attributes that don't
affect the schema.
"""
with connection.schema_editor() as editor:
editor.create_model(Author)
editor.create_model(Book)
old_field = Book._meta.get_field('author')
new_field = ForeignKey(
Author,
blank=True,
editable=False,
error_messages={'invalid': 'error message'},
help_text='help text',
limit_choices_to={'limit': 'choice'},
on_delete=PROTECT,
related_name='related_name',
related_query_name='related_query_name',
validators=[lambda x: x],
verbose_name='verbose name',
)
new_field.set_attributes_from_name('author')
with connection.schema_editor() as editor, self.assertNumQueries(0):
editor.alter_field(Book, old_field, new_field, strict=True)
with connection.schema_editor() as editor, self.assertNumQueries(0):
editor.alter_field(Book, new_field, old_field, strict=True)
def test_add_textfield_unhashable_default(self): def test_add_textfield_unhashable_default(self):
# Create the table # Create the table
with connection.schema_editor() as editor: with connection.schema_editor() as editor: