--fake-initial vs --fake in Django migration?

Short answer

  • --fake does not apply the migration
  • --fake-initial might, or might not apply the migration

Longer answer:

--fake: Django keeps a table called django_migrations to know which migrations it has applied in the past, to prevent you from accidentally applying them again. All --fake does is insert the migration filename into that table, without actually running the migration. This is useful if you manually changed the database schema first, and the models later, and want to bypass django's actions. However, during that step you are on your own, so take care that you don't end up in an inconsistent state.

--fake-initial: depends on the state of the database

  • all of the tables already exist in the database: in that case, it works like --fake. Only the names of the tables are checked, not their actual schema, so, again, take care
  • none of the tables already exist in the database: in that case, it works like a normal migration
  • some of the table already exist: you get an error. That's not supposed to happen, either you take care of the database, or django does.

Note that, --fake-initial is only taken into account if the migration file has initial=True in its class, otherwise the flag is ignored. Also, this is the only documented usage of initial=True in migrations.


@e4c5 already gave an answer about this question, but I would like to add one more thing concerning when to use --fake and --fake-initial.

Suppose you have a database from production and you want to use it for development and apply migrations without destroying the data. In that case --fake-initial comes in handy.

The --fake-initial will force Django to look at your migration files and basically skip the creation of tables that are already in your database. Do note, though, that any migrations that don’t create tables (but rather modify existing tables) will be run.

Conversely, If you have an existing project with migration files and you want to reset the history of existing migrations, then --fake is usually used.


Well the documentation is very clear about this

--fake-initial

Allows Django to skip an app’s initial migration if all database tables with the names of all models created by all CreateModel operations in that migration already exist. This option is intended for use when first running migrations against a database that preexisted the use of migrations. This option does not, however, check for matching database schema beyond matching table names

You were asking about the risks, well here it is

only safe to use if you are confident that your existing schema matches what is recorded in your initial migration.

--fake

Tells Django to mark the migrations as having been applied or unapplied, but without actually running the SQL to change your database schema.

This is intended for advanced users to manipulate the current migration state directly if they’re manually applying changes;

Once again risks are clearly highlighted

be warned that using --fake runs the risk of putting the migration state table into a state where manual recovery will be needed to make migrations run correctly.

This answer is valid not just for django versions 1.8+ but for other versions as well.

edit Nov, 2018: I sometimes I see answers here and elsewhere that suggest that you should drop your databae. That's almost never the right thing to do. If you drop your database you lose all your data.