﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
31954	MigrationOptimizer mangles operation order if app name contains uppercase letters.	Koen De Wit	Koen De Wit	"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`. "	Bug	closed	Migrations	3.1	Normal	fixed			Ready for checkin	1	0	0	0	0	0
