#31954: MigrationOptimizer mangles operation order if app name contains
uppercase
letters
--------------------------------------+---------------------------
Reporter: koendewit | Owner: koendewit
Type: Bug | Status: assigned
Component: Migrations | Version: 3.1
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
--------------------------------------+---------------------------
I am aware that app names are preferably all-lowercase according to
[https://www.python.org/dev/peps/pep-0008/#package-and-module-names PEP
8], but uppercase letters are nevertheless valid.
Steps to reproduce:
* Create a new project and an app with uppercase letters in the app name :
{{{
django-admin startproject mysite
cd mysite
python manage.py startapp MyApp
}}}
* Add `'MyApp'` to the `INSTALLED_APPS` in `mysite/settings.py`
* Edit `MyApp/models.py` :
{{{#!python
from django.db import models
class RefModel(models.Model):
pass
class BaseModel(models.Model):
r = models.ForeignKey(RefModel, on_delete=models.PROTECT)
class SubModel(BaseModel):
pass
}}}
* Run `python ./manage.py makemigrations` . In the resulting migration
file, the create operation for `SubModel` comes before the create
operation for `BaseModel`, which is wrong.
* Run `python ./manage.py migrate` , which will fail with this error:
{{{
Operations to perform:
Apply all migrations: MyApp, admin, auth, contenttypes, sessions
Running migrations:
Applying MyApp.0001_initial...Traceback (most recent call last):
File "./manage.py", line 22, in <module>
main()
File "./manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/core/management/__init__.py", line 401, in
execute_from_command_line
utility.execute()
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/core/management/__init__.py", line 395, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/core/management/base.py", line 330, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/core/management/base.py", line 371, in execute
output = self.handle(*args, **options)
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/core/management/base.py", line 85, in wrapped
res = handle_func(*args, **kwargs)
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/core/management/commands/migrate.py", line 243, in handle
post_migrate_state = executor.migrate(
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/db/migrations/executor.py", line 117, in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake,
fake_initial=fake_initial)
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/db/migrations/executor.py", line 147, in
_migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake,
fake_initial=fake_initial)
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/db/migrations/executor.py", line 227, in apply_migration
state = migration.apply(state, schema_editor)
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/db/migrations/migration.py", line 114, in apply
operation.state_forwards(self.app_label, project_state)
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/db/migrations/operations/models.py", line 80, in
state_forwards
state.add_model(ModelState(
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/db/migrations/state.py", line 95, in add_model
self.reload_model(app_label, model_name)
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/db/migrations/state.py", line 156, in reload_model
self._reload(related_models)
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/db/migrations/state.py", line 189, in _reload
self.apps.render_multiple(states_to_be_rendered)
File "/home/koen/.virtualenvs/dtest/lib/python3.8/site-
packages/django/db/migrations/state.py", line 310, in render_multiple
raise InvalidBasesError(
django.db.migrations.exceptions.InvalidBasesError: Cannot resolve bases
for [<ModelState: 'MyApp.SubModel'>]
This can happen if you are inheriting models from an app with migrations
(e.g. contrib.auth)
in an app with no migrations; see
https://docs.djangoproject.com/en/3.1/topics/migrations/#dependencies for
more
}}}
This bug does not occur if the app name is all-lowercase.
Digging into the code, I found that the MigrationOptimizer will combine
two operations (Create model `BaseModel` and add ForeignKey-field `r` to
`BaseModel`) without taking into account that `SubModel` depends on
`BaseModel`.
--
Ticket URL: <https://code.djangoproject.com/ticket/31954>
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/052.314d4f311f1677b09c020b6813148b05%40djangoproject.com.