#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.

Reply via email to