#35359: Got `django.core.exceptions.FieldError` when adding GeneratedField
--------------------------------------+--------------------------------
Reporter: wd0517 | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: 5.0
Severity: Normal | Keywords: GeneratedField
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
--------------------------------------+--------------------------------
Here is an exists model
{{{
class Foo1(models.Model):
age = models.IntegerField()
}}}
Then adding GeneratedField
{{{
class Foo1(models.Model):
age = models.IntegerField()
name = models.CharField(max_length=10)
lower_name = models.GeneratedField(
expression=Lower("name"),
output_field=models.CharField(max_length=11),
db_persist=True,
)
}}}
Run makemigrations get below file
{{{
class Migration(migrations.Migration):
dependencies = [
('temp_django_test', '0006_foo1'),
]
operations = [
migrations.AddField(
model_name='foo1',
name='lower_name',
field=models.GeneratedField(db_persist=True,
expression=django.db.models.functions.text.Lower('name'),
output_field=models.CharField(max_length=11)),
),
migrations.AddField(
model_name='foo1',
name='name',
field=models.CharField(default='a', max_length=10),
preserve_default=False,
),
]
}}}
Then run migrate, will got error
{{{
temp-django-5.0 ❯ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions,
temp_django_test
Running migrations:
Applying temp_django_test.0007_foo1_lower_name_foo1_name...Traceback
(most recent call last):
File "/Users/wangdi/Desktop/test_scripts.nosync/temp-
django-5.0/manage.py", line 22, in <module>
main()
File "/Users/wangdi/Desktop/test_scripts.nosync/temp-
django-5.0/manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "/Users/wangdi/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/core/management/__init__.py", line 442, in
execute_from_command_line
utility.execute()
File "/Users/wangdi/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/core/management/__init__.py", line 436, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/wangdi/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/core/management/base.py", line 413, in run_from_argv
self.execute(*args, **cmd_options)
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/core/management/base.py", line 459, in execute
output = self.handle(*args, **options)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/core/management/base.py", line 107, in wrapper
res = handle_func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/core/management/commands/migrate.py", line 356, in handle
post_migrate_state = executor.migrate(
^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/migrations/executor.py", line 135, in migrate
state = self._migrate_all_forwards(
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/migrations/executor.py", line 167, in
_migrate_all_forwards
state = self.apply_migration(
^^^^^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/migrations/executor.py", line 252, in apply_migration
state = migration.apply(state, schema_editor)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/migrations/migration.py", line 132, in apply
operation.database_forwards(
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/migrations/operations/fields.py", line 108, in
database_forwards
schema_editor.add_field(
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/backends/mysql/schema.py", line 103, in add_field
super().add_field(model, field)
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/backends/base/schema.py", line 709, in add_field
definition, params = self.column_sql(model, field,
include_default=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/backends/base/schema.py", line 369, in column_sql
" ".join(
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/backends/base/schema.py", line 336, in _iter_column_sql
generated_sql, generated_params = self._column_generated_sql(field)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/backends/base/schema.py", line 434, in
_column_generated_sql
expression_sql, params = field.generated_sql(self.connection)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/models/fields/generated.py", line 58, in generated_sql
resolved_expression = self.expression.resolve_expression(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/models/expressions.py", line 975, in resolve_expression
c.source_expressions[pos] = arg.resolve_expression(
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/models/expressions.py", line 854, in resolve_expression
return query.resolve_ref(
self.name, allow_joins, reuse, summarize)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/models/sql/query.py", line 2014, in resolve_ref
join_info = self.setup_joins(
^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/models/sql/query.py", line 1867, in setup_joins
path, final_field, targets, rest = self.names_to_path(
^^^^^^^^^^^^^^^^^^^
File "/Users/wd0517/Desktop/test_scripts.nosync/temp-
django-5.0/.venv/lib/python3.11/site-
packages/django/db/models/sql/query.py", line 1772, in names_to_path
raise FieldError(
django.core.exceptions.FieldError: Cannot resolve keyword 'name' into
field. Choices are: age, id, lower_name
}}}
Environment:
- Python 3.11.8
- Django 5.0.4
- MySQL 8.0.34
I think the bug is caused by the order of operations in Migration, after
adjusting it, then can be migrate successfully
--
Ticket URL: <
https://code.djangoproject.com/ticket/35359>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.