#33234: Migrations autodetector breaking with proxy models inheriting from mixin
---------------------------------+------------------------------------
     Reporter:  Kevin Marsh      |                    Owner:  nobody
         Type:  Bug              |                   Status:  new
    Component:  Migrations       |                  Version:  4.0
     Severity:  Release blocker  |               Resolution:
     Keywords:  proxy model      |             Triage Stage:  Accepted
    Has patch:  0                |      Needs documentation:  0
  Needs tests:  0                |  Patch needs improvement:  0
Easy pickings:  0                |                    UI/UX:  0
---------------------------------+------------------------------------
Changes (by Mariusz Felisiak):

 * cc: David Wobrock (added)
 * stage:  Unreviewed => Accepted
 * severity:  Normal => Release blocker


Old description:

> So I've run into an issue with the new automigrations feature in Django
> 4.0b1 (and 4.0a1)  relating to proxy models inheriting from a non-Model
> class.
>
> For examples given these three models:
> {{{#!python
> from django.db import models
>
> class MyMixin:
>         ...
>
> class MyRealModel(MyMixin, models.Model):
>         ...
>
> class MyBaseModel(models.Model):
>         ...
>
> class MyProxyModel(MyMixin, MyBaseModel):
>         class Meta:
>                 proxy = True
> }}}
>
> Running `migrate`/`makemigrations` will result in `MyProxyModel` crashing
> when it tries running `_find_concrete_model_from_proxy`:
> {{{
>   File
> "/some/annonymized/path/django/core/management/commands/makemigrations.py",
> line 172, in handle
>     changes = autodetector.changes(
>   File "/some/annonymized/path/django/db/migrations/autodetector.py",
> line 43, in changes
>     changes = self._detect_changes(convert_apps, graph)
>   File "/some/annonymized/path/django/db/migrations/autodetector.py",
> line 156, in _detect_changes
>     self.to_state.resolve_fields_and_relations()
>   File "/some/annonymized/path/django/db/migrations/state.py", line 449,
> in resolve_fields_and_relations
>     concretes, proxies =
> self._get_concrete_models_mapping_and_proxy_models()
>   File "/some/annonymized/path/django/db/migrations/state.py", line 470,
> in _get_concrete_models_mapping_and_proxy_models
>     concrete_models_mapping[model_key] =
> self._find_concrete_model_from_proxy(
>   File "/some/annonymized/path/django/db/migrations/state.py", line 479,
> in _find_concrete_model_from_proxy
>     base_key = make_model_tuple(base)
>   File "/some/annonymized/path/django/db/models/utils.py", line 18, in
> make_model_tuple
>     model_tuple = model._meta.app_label, model._meta.model_name
> AttributeError: type object 'MyMixin' has no attribute '_meta'
> }}}
>

> Changing `MyMixin` to inherit from `models.Model` prevents this crash but
> might not always be possible depending on how the user is using that
> mixin. Or if we've decided that all inheritance for proxy models must be
> from `models.Model` then that should be flagged up more explicitly to
> developers (eg. checking for it in `ModelBase.__new__` or something).

New description:

 So I've run into an issue with the new automigrations feature in Django
 4.0b1 (and 4.0a1)  relating to proxy models inheriting from a non-Model
 class.

 For examples given these three models:
 {{{#!python
 from django.db import models

 class MyMixin:
         ...

 class MyBaseModel(models.Model):
         ...

 class MyProxyModel(MyMixin, MyBaseModel):
         class Meta:
                 proxy = True
 }}}

 Running `migrate`/`makemigrations` will result in `MyProxyModel` crashing
 when it tries running `_find_concrete_model_from_proxy`:
 {{{
   File
 "/some/annonymized/path/django/core/management/commands/makemigrations.py",
 line 172, in handle
     changes = autodetector.changes(
   File "/some/annonymized/path/django/db/migrations/autodetector.py", line
 43, in changes
     changes = self._detect_changes(convert_apps, graph)
   File "/some/annonymized/path/django/db/migrations/autodetector.py", line
 156, in _detect_changes
     self.to_state.resolve_fields_and_relations()
   File "/some/annonymized/path/django/db/migrations/state.py", line 449,
 in resolve_fields_and_relations
     concretes, proxies =
 self._get_concrete_models_mapping_and_proxy_models()
   File "/some/annonymized/path/django/db/migrations/state.py", line 470,
 in _get_concrete_models_mapping_and_proxy_models
     concrete_models_mapping[model_key] =
 self._find_concrete_model_from_proxy(
   File "/some/annonymized/path/django/db/migrations/state.py", line 479,
 in _find_concrete_model_from_proxy
     base_key = make_model_tuple(base)
   File "/some/annonymized/path/django/db/models/utils.py", line 18, in
 make_model_tuple
     model_tuple = model._meta.app_label, model._meta.model_name
 AttributeError: type object 'MyMixin' has no attribute '_meta'
 }}}


 Changing `MyMixin` to inherit from `models.Model` prevents this crash but
 might not always be possible depending on how the user is using that
 mixin. Or if we've decided that all inheritance for proxy models must be
 from `models.Model` then that should be flagged up more explicitly to
 developers (eg. checking for it in `ModelBase.__new__` or something).

--

Comment:

 Thanks for the report!

 Regression in aa4acc164d1247c0de515c959f7b09648b57dc42.
 Reproduced at afeafd6036616bac8263d762c1610f22241c0187.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/33234#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/068.60304f56a5a4032116a561b221f6e176%40djangoproject.com.

Reply via email to