If you need to migrate Django model, and it happens to be an AUTH_USER_MODEL

Ray Zhu
2 min readJan 28, 2021

Hope you never need this. Here are clues I can manage to write down before I forgot any steps. The steps are not verified because I don’t want to do it again.

If the model you are migrating is not an AUTH_USER_MODEL, follow this.
I would copy those steps here and modify them to migrate AUTH_USER_MODEL.

Assume we have these migration files in the beginning: 0001_initial_in_app1.py , 0001_initial_in_app2.py

  1. Copy the AUTH_USER_MODEL from app1 to app2, set db_table, and DO NOT change any foreign key references.
  2. Run makemigrations . Assume the generated migration files are named 0002_migration_app1.py and 0002_migrration_app2.py . Wrap both migration files in state_operations like the following:

In 0002_migration_app1.py

operations = [
...
migrations.DeleteModel(
name='YourModel',
),
...
]

becomes

operations = [
migrations.SeparateDatabaseAndState(state_operations=[
...
migrations.DeleteModel(
name='YourModel',
),
...
])
]

3. Add a dependency, ('app1', '0002_migration_app1'), in the 0002_migration_app2.py

4. Point all of the foreign key references to the new model.
If you aren’t using string references, give the imported model an alias (DO NOT remove it) so it does not compete with the imported class.

5. Run makemigrations to let the foreign changes actually happen. Assume the generated file is called 0003_change_fk_app2.py.

6. Add ('app2', '0002_migration_app2') as a dependency in 0003_change_fk_app2.py.

7. Temporarily remove the models from app1.

8. Make AUTH_USER_MODEL points to app2.YOUR_MODEL.
If any past model has ever point to AUTH_USER_MODEL, it would point to new model now. If Django complains about conflict column names in step 10, make them as None, run makemigrations, adjust 0002_migration_app2.py accordingly, and try it out.

9. Move initial = True from 0001_initial_in_app2.py to 0002_migration_app2.py and make dependency in 0001_initial_in_app2.py as ('app2', '0002_migration_app2') only. And add ('auth', '__first__') as an extra dependency in 0002_migration_app2.py

10. Run makemigrations. Assume this generate file 0003_delete_model_app1.py. And wrap 0003_delete_model_app1.py in state_operations. Add ('app2', '0003_change_fk_app2') as a dependency in 0003_delete_model_app1.py. If Django is fine about the change, and revoke the changes in step 8.

11. Run python manage.py dbshell and execute DELETE FROM django_migrations WHERE app IN ("app1", "app2", "account", "admin", "authtoken", "socialaccount", auth");

12. Run the following commands:

python manage.py migrate --fake app1 0001
python manage.py migrate app2 0002
python manage.py migrate --fake account
python manage.py migrate --fake admin
python manage.py migrate --fake authtoken
python manage.py migrate --fake socialaccount
python manage.py migrate --fake auth
python manage.py migrate --fake main
python manage.py migrate app1
python manage.py migrate app2

13. Copy 0001_initial_in_app1.py to 0002_migration_app2.py and remove 0003_change_fk_app2.py in app2 .

14. You may delete app1.

(Optional) Remove db_table in app2.YOUR_MODEL and run makemigrations(This would give you 0003_change_table_name_app2.py), migrate again to apply new table name.

--

--