[Django]-Django migrate –fake and –fake-initial explained

104👍

It is related to a database problem similar to a merge conflict in a source code (git) if you need to combine two branches with similar models or to switch between them. Nobody likes it intentionally.

Imagine that you started to modify an application last week, maybe because you found a bug or you extended the app by a field or table. Today you received an update and you have a problem, because there is a migration that adds a field that is still in your database and you can apply only other parts of that migration. You look at SQL contents of the migration by running

./manage sqlmigrate some_app 0007_new_migration >customized-some_app-0007_new_migration.sql

compare the content with the change made last week and remove or comment out a command that is still applied and can not be repeated. Run all remaining SQL manually. Mark that migration like it would be applied automatically:

./manage migrate --fake some_app 0007_new_migration

If you break something, nobody can help you probably, because the migration system will not know the current state of the database more. Therefore do a backup, write notes, use a sandbox and work precisely.

EDIT: The migration table django_migrations is a simple list of migrations applied in all apps. Rows in this table should be always in a synchronized status with the database structure. Migrations can be applied by a normal migrate. (or un-applied by a reverse migration to an older state, usually with some data loss of course) A fake migration applies the change only to the django_migrations table.

me => select * from django_migrations;
 id | app      |          name           |            applied            
----+----------+-------------------------+-------------------------------
  1 | some_app | 0001_initial            | 2017-10-16 06:11:07.31249+02
  2 | some_app | 0002_auto_20171016_1905 | 2017-10-17 02:05:48.979295+02

A migration (file) is a description of incremental change and also information to be possible to evaluate the difference between models.py since the last migration, that is compared when running makemigrations. It is enough also in the case where some tables were un-managed initially and they could become managed later. (therefore unmanaged tables are also recorded.)

EDIT: An example: how sqlmigrate with --fake could be used to fix a broken database by migrations (to recreate a deleted table).

EDIT: Example: If you decided to delete tables of some application and to create them again by migrate (be warned and see my comment below), you probably also want to reset all migrations of that application first, including the initial migration, by a pseudo-migration name "zero".
./manage migrate --fake some_app zero.

Leave a comment