mirror of
https://github.com/django/django.git
synced 2024-11-24 02:47:35 +01:00
Fixed #33471 -- Made AlterField operation a noop when changing "choices".
This also allows customizing attributes of fields that don't affect a column definition.
This commit is contained in:
parent
6991880109
commit
65effbdb10
@ -1376,22 +1376,9 @@ class BaseDatabaseSchemaEditor:
|
||||
# - 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
|
||||
non_database_attrs = [
|
||||
"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:
|
||||
for attr in old_field.non_db_attrs:
|
||||
old_kwargs.pop(attr, None)
|
||||
for attr in new_field.non_db_attrs:
|
||||
new_kwargs.pop(attr, None)
|
||||
return self.quote_name(old_field.column) != self.quote_name(
|
||||
new_field.column
|
||||
|
@ -140,6 +140,24 @@ class Field(RegisterLookupMixin):
|
||||
system_check_deprecated_details = None
|
||||
system_check_removed_details = None
|
||||
|
||||
# Attributes that don't affect a column definition.
|
||||
# These attributes are ignored when altering the field.
|
||||
non_db_attrs = (
|
||||
"blank",
|
||||
"choices",
|
||||
"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",
|
||||
)
|
||||
|
||||
# Field flags
|
||||
hidden = False
|
||||
|
||||
|
@ -314,6 +314,26 @@ reconstructing the field::
|
||||
new_instance = MyField(*args, **kwargs)
|
||||
self.assertEqual(my_field_instance.some_attribute, new_instance.some_attribute)
|
||||
|
||||
.. _custom-field-non_db_attrs:
|
||||
|
||||
Field attributes not affecting database column definition
|
||||
---------------------------------------------------------
|
||||
|
||||
.. versionadded:: 4.1
|
||||
|
||||
You can override ``Field.non_db_attrs`` to customize attributes of a field that
|
||||
don't affect a column definition. It's used during model migrations to detect
|
||||
no-op ``AlterField`` operations.
|
||||
|
||||
For example::
|
||||
|
||||
class CommaSepField(models.Field):
|
||||
|
||||
@property
|
||||
def non_db_attrs(self):
|
||||
return super().non_db_attrs + ("separator",)
|
||||
|
||||
|
||||
Changing a custom field's base class
|
||||
------------------------------------
|
||||
|
||||
|
@ -288,6 +288,10 @@ Models
|
||||
on MariaDB and MySQL. For databases that do not support ``XOR``, the query
|
||||
will be converted to an equivalent using ``AND``, ``OR``, and ``NOT``.
|
||||
|
||||
* The new :ref:`Field.non_db_attrs <custom-field-non_db_attrs>` attribute
|
||||
allows customizing attributes of fields that don't affect a column
|
||||
definition.
|
||||
|
||||
Requests and Responses
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -3961,6 +3961,20 @@ class SchemaTests(TransactionTestCase):
|
||||
with connection.schema_editor() as editor, self.assertNumQueries(0):
|
||||
editor.alter_field(Book, new_field, old_field, strict=True)
|
||||
|
||||
def test_alter_field_choices_noop(self):
|
||||
with connection.schema_editor() as editor:
|
||||
editor.create_model(Author)
|
||||
old_field = Author._meta.get_field("name")
|
||||
new_field = CharField(
|
||||
choices=(("Jane", "Jane"), ("Joe", "Joe")),
|
||||
max_length=255,
|
||||
)
|
||||
new_field.set_attributes_from_name("name")
|
||||
with connection.schema_editor() as editor, self.assertNumQueries(0):
|
||||
editor.alter_field(Author, old_field, new_field, strict=True)
|
||||
with connection.schema_editor() as editor, self.assertNumQueries(0):
|
||||
editor.alter_field(Author, new_field, old_field, strict=True)
|
||||
|
||||
def test_add_textfield_unhashable_default(self):
|
||||
# Create the table
|
||||
with connection.schema_editor() as editor:
|
||||
|
Loading…
Reference in New Issue
Block a user