#33449: Migration autodetector fails for models with field named _order, but not
using Meta.order_with_respect_to
--------------------------------+--------------------------------------
     Reporter:  Fabian Büchler  |                    Owner:  nobody
         Type:  Bug             |                   Status:  new
    Component:  Migrations      |                  Version:  4.0
     Severity:  Normal          |               Resolution:
     Keywords:                  |             Triage Stage:  Unreviewed
    Has patch:  0               |      Needs documentation:  0
  Needs tests:  0               |  Patch needs improvement:  0
Easy pickings:  0               |                    UI/UX:  0
--------------------------------+--------------------------------------
Description changed by Fabian Büchler:

Old description:

> The commit
> [aa4acc1|https://github.com/django/django/commit/aa4acc164d1247c0de515c959f7b09648b57dc42]
> introduced a new function `ModelState.get_field` in
> `django.db.migrations.state`.
>
> This converts the field name `_order` to the one defined in
> `options['order_with_respect_to']` automatically, which fails if the
> model has a field `_order` but isn't using `Meta.order_with_respect_to`.
>
> That is the case for models generated by django-simple-history
> (https://github.com/jazzband/django-simple-history) for models that are
> originally using `Meta.order_with_respect_to`: the resulting historical
> records model has only `_order` but is not using the Meta option.
>

> This shows when running `mange.py migrate` or `manage.py makemigrations`:
>

>
> {{{#!python
> $ ./manage.py makemigrations --dry-run
> Waiting for port 'mysql:3306' timeout 1s (attempt 1/60)
> Port 'mysql:3306' is open
> Traceback (most recent call last):
>   File "./manage.py", line 42, in <module>
>     main()
>   File "./manage.py", line 36, in main
>     execute_from_command_line(sys.argv)
>   File "/usr/local/lib/python3.8/site-
> packages/django/core/management/__init__.py", line 425, in
> execute_from_command_line
>     utility.execute()
>   File "/usr/local/lib/python3.8/site-
> packages/django/core/management/__init__.py", line 419, in execute
>     self.fetch_command(subcommand).run_from_argv(self.argv)
>   File "/usr/local/lib/python3.8/site-
> packages/django/core/management/base.py", line 373, in run_from_argv
>     self.execute(*args, **cmd_options)
>   File "/usr/local/lib/python3.8/site-
> packages/django/core/management/base.py", line 417, in execute
>     output = self.handle(*args, **options)
>   File "/usr/local/lib/python3.8/site-
> packages/django/core/management/base.py", line 90, in wrapped
>     res = handle_func(*args, **kwargs)
>   File "/usr/local/lib/python3.8/site-
> packages/django/core/management/commands/makemigrations.py", line 172, in
> handle
>     changes = autodetector.changes(
>   File "/usr/local/lib/python3.8/site-
> packages/django/db/migrations/autodetector.py", line 43, in changes
>     changes = self._detect_changes(convert_apps, graph)
>   File "/usr/local/lib/python3.8/site-
> packages/django/db/migrations/autodetector.py", line 189, in
> _detect_changes
>     self.generate_altered_fields()
>   File "/usr/local/lib/python3.8/site-
> packages/django/db/migrations/autodetector.py", line 928, in
> generate_altered_fields
>     old_field = self.from_state.models[app_label,
> old_model_name].get_field(old_field_name)
>   File "/usr/local/lib/python3.8/site-
> packages/django/db/migrations/state.py", line 689, in get_field
>     self.options['order_with_respect_to']
> KeyError: 'order_with_respect_to'
> }}}
>

> I believe this could be solved using a bit more defensive code, like:
>
> {{{#!python
>     def get_field(self, field_name):
>         if field_name == '_order' and 'order_with_respect_to' in
> self.options:
>             field_name = self.options['order_with_respect_to']
>         return self.fields[field_name]
> }}}

New description:

 The commit
 
https://github.com/django/django/commit/aa4acc164d1247c0de515c959f7b09648b57dc42
 introduced a new function `ModelState.get_field` in
 `django.db.migrations.state`.

 This converts the field name `_order` to the one defined in
 `options['order_with_respect_to']` automatically, which fails if the model
 has a field `_order` but isn't using `Meta.order_with_respect_to`.

 That is the case for models generated by django-simple-history
 (https://github.com/jazzband/django-simple-history) for models that are
 originally using `Meta.order_with_respect_to`: the resulting historical
 records model has only `_order` but is not using the Meta option.


 This shows when running `mange.py migrate` or `manage.py makemigrations`:



 {{{#!python
 $ ./manage.py makemigrations --dry-run
 Waiting for port 'mysql:3306' timeout 1s (attempt 1/60)
 Port 'mysql:3306' is open
 Traceback (most recent call last):
   File "./manage.py", line 42, in <module>
     main()
   File "./manage.py", line 36, in main
     execute_from_command_line(sys.argv)
   File "/usr/local/lib/python3.8/site-
 packages/django/core/management/__init__.py", line 425, in
 execute_from_command_line
     utility.execute()
   File "/usr/local/lib/python3.8/site-
 packages/django/core/management/__init__.py", line 419, in execute
     self.fetch_command(subcommand).run_from_argv(self.argv)
   File "/usr/local/lib/python3.8/site-
 packages/django/core/management/base.py", line 373, in run_from_argv
     self.execute(*args, **cmd_options)
   File "/usr/local/lib/python3.8/site-
 packages/django/core/management/base.py", line 417, in execute
     output = self.handle(*args, **options)
   File "/usr/local/lib/python3.8/site-
 packages/django/core/management/base.py", line 90, in wrapped
     res = handle_func(*args, **kwargs)
   File "/usr/local/lib/python3.8/site-
 packages/django/core/management/commands/makemigrations.py", line 172, in
 handle
     changes = autodetector.changes(
   File "/usr/local/lib/python3.8/site-
 packages/django/db/migrations/autodetector.py", line 43, in changes
     changes = self._detect_changes(convert_apps, graph)
   File "/usr/local/lib/python3.8/site-
 packages/django/db/migrations/autodetector.py", line 189, in
 _detect_changes
     self.generate_altered_fields()
   File "/usr/local/lib/python3.8/site-
 packages/django/db/migrations/autodetector.py", line 928, in
 generate_altered_fields
     old_field = self.from_state.models[app_label,
 old_model_name].get_field(old_field_name)
   File "/usr/local/lib/python3.8/site-
 packages/django/db/migrations/state.py", line 689, in get_field
     self.options['order_with_respect_to']
 KeyError: 'order_with_respect_to'
 }}}


 I believe this could be solved using a bit more defensive code, like:

 {{{#!python
     def get_field(self, field_name):
         if field_name == '_order' and 'order_with_respect_to' in
 self.options:
             field_name = self.options['order_with_respect_to']
         return self.fields[field_name]
 }}}

--

-- 
Ticket URL: <https://code.djangoproject.com/ticket/33449#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/072.b3fe113cc2cc4330c7ab95a83e7ce5e9%40djangoproject.com.

Reply via email to