#34877: KeyError for output_field in GeneratedField
-------------------------------------+-------------------------------------
Reporter: Paolo Melchiorre | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 5.0
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: field, database, | Triage Stage:
generated, output_field | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by Paolo Melchiorre:
Old description:
> Trying to get SQL code for a migrations I receive a `KeyEorr`
>
> **Model**
>
> {{{#!python
> from decimal import Decimal
> from django.db import models
> from django.db.models import F, Value as V
> from django.db.models.functions import Round
>
> class Item(models.Model):
> price = models.DecimalField(max_digits=7, decimal_places=2)
> vat_price = models.GeneratedField(
> db_persist=True,
> expression=Round(F("price") * V(Decimal("1.22")), 2),
> output_field=models.DecimalField(max_digits=8, decimal_places=2),
> )
> }}}
>
> **Step**
>
> {{{#!bash
> $ python -m manage makemigrations
> $ python -m manage sqlmigrate shop 0001
> }}}
>
> **Traceback**
>
> {{{#!pycon
> Traceback (most recent call last):
> File "<frozen runpy>", line 198, in _run_module_as_main
> File "<frozen runpy>", line 88, in _run_code
> File "/home/paulox/Projects/generatedfield/manage.py", line 22, in
> <module>
> main()
> File "/home/paulox/Projects/generatedfield/manage.py", line 18, in main
> execute_from_command_line(sys.argv)
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/core/management/__init__.py", line 442, in
> execute_from_command_line
> utility.execute()
> File "/home/paulox/Projects/generatedfield/.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 "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/core/management/base.py", line 412, in run_from_argv
> self.execute(*args, **cmd_options)
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/core/management/commands/sqlmigrate.py", line 38, in
> execute
> return super().execute(*args, **options)
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/core/management/base.py", line 458, in execute
> output = self.handle(*args, **options)
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/core/management/commands/sqlmigrate.py", line 80, in
> handle
> sql_statements = loader.collect_sql(plan)
> ^^^^^^^^^^^^^^^^^^^^^^^^
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/db/migrations/loader.py", line 381, in collect_sql
> state = migration.apply(state, schema_editor, collect_sql=True)
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/db/migrations/migration.py", line 132, in apply
> operation.database_forwards(
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/db/migrations/operations/models.py", line 96, in
> database_forwards
> schema_editor.create_model(model)
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/db/backends/base/schema.py", line 506, in create_model
> self.deferred_sql.extend(self._model_indexes_sql(model))
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/db/backends/base/schema.py", line 1595, in
> _model_indexes_sql
> output.extend(self._field_indexes_sql(model, field))
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/db/backends/postgresql/schema.py", line 63, in
> _field_indexes_sql
> like_index_statement = self._create_like_index_sql(model, field)
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/db/backends/postgresql/schema.py", line 88, in
> _create_like_index_sql
> db_type = field.db_type(connection=self.connection)
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/db/models/fields/__init__.py", line 879, in db_type
> return column_type % data
> ~~~~~~~~~~~~^~~~~~
> File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
> packages/django/utils/datastructures.py", line 280, in __getitem__
> value = super().__getitem__(key)
> ^^^^^^^^^^^^^^^^^^^^^^^^
> KeyError: 'max_digits'
> }}}
New description:
Trying to get SQL code for a migration I receive a `KeyError`.
**Model**
Example of a model with a `GenratedField`.
{{{#!python
from decimal import Decimal
from django.db import models
from django.db.models import F, Value as V
from django.db.models.functions import Round
class Item(models.Model):
price = models.DecimalField(max_digits=7, decimal_places=2)
vat_price = models.GeneratedField(
db_persist=True,
expression=Round(F("price") * V(Decimal("1.22")), 2),
output_field=models.DecimalField(max_digits=8, decimal_places=2),
)
}}}
**Step**
Generate the migration file:
{{{#!bash
$ python -m manage makemigrations
}}}
Steps to generate the error:
{{{#!bash
$ python -m manage sqlmigrate shop 0001
}}}
Similar error with another command:
{{{#!bash
$ python -m manage migrate shop 0001
}}}
**Traceback**
{{{#!pycon
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/home/paulox/Projects/generatedfield/manage.py", line 22, in
<module>
main()
File "/home/paulox/Projects/generatedfield/manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/core/management/__init__.py", line 442, in
execute_from_command_line
utility.execute()
File "/home/paulox/Projects/generatedfield/.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 "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/core/management/base.py", line 412, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/core/management/commands/sqlmigrate.py", line 38, in
execute
return super().execute(*args, **options)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/core/management/base.py", line 458, in execute
output = self.handle(*args, **options)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/core/management/commands/sqlmigrate.py", line 80, in
handle
sql_statements = loader.collect_sql(plan)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/db/migrations/loader.py", line 381, in collect_sql
state = migration.apply(state, schema_editor, collect_sql=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/db/migrations/migration.py", line 132, in apply
operation.database_forwards(
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/db/migrations/operations/models.py", line 96, in
database_forwards
schema_editor.create_model(model)
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/db/backends/base/schema.py", line 506, in create_model
self.deferred_sql.extend(self._model_indexes_sql(model))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/db/backends/base/schema.py", line 1595, in
_model_indexes_sql
output.extend(self._field_indexes_sql(model, field))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/db/backends/postgresql/schema.py", line 63, in
_field_indexes_sql
like_index_statement = self._create_like_index_sql(model, field)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/db/backends/postgresql/schema.py", line 88, in
_create_like_index_sql
db_type = field.db_type(connection=self.connection)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/db/models/fields/__init__.py", line 879, in db_type
return column_type % data
~~~~~~~~~~~~^~~~~~
File "/home/paulox/Projects/generatedfield/.venv/lib/python3.11/site-
packages/django/utils/datastructures.py", line 280, in __getitem__
value = super().__getitem__(key)
^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: 'max_digits'
}}}
**Expected result**
{{{#!sql
BEGIN;
--
-- Create model Item
--
CREATE TABLE "shop_item" (
"id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
"price" numeric(7, 2) NOT NULL,
"vat_price" numeric(8, 2) GENERATED ALWAYS AS (ROUND(("price" * 1.22),
2)) STORED
);
COMMIT;
}}}
--
--
Ticket URL: <https://code.djangoproject.com/ticket/34877#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/0107018ad8108664-0f97438f-6916-4ee5-9a9b-55a07c8f892f-000000%40eu-central-1.amazonses.com.