27

Using django 1.7.7 I want to use django's migration to add or remove a field. so I modified model.py and ran

python manage.py makemigrations myproj
Migrations for 'myproj':
  0001_initial.py:
    - Create model Interp
    - Create model InterpVersion

python manage.py migrate myproj
Operations to perform:
  Apply all migrations: myproj
Running migrations:
  Applying myproj.0001_initial... FAKED

python manage.py runserver

Then checked the admin page, it is not updated. Then I tried removing the migration folder and tried again; the migrate command says there are no migrations to apply.

How can I do the migration? Note: I want to use the new technique using django's migration not the old south approach.

max
  • 9,708
  • 15
  • 89
  • 144
  • Is myproj added to the INSTALLED_APPS? – Jordan Apr 27 '15 at 17:38
  • Seems strange that it would give you a `0001_initial` for models that have previously been created. Did you update from an older Django version? – sthzg Apr 27 '15 at 17:43
  • No. Just a clean start with django 1.7.7. – max Apr 27 '15 at 17:45
  • Go to you migration folder, delete `0001_initial.py` file then run `python manage.py makemigrations myproj` then run `python manage.py migrate`. This is your initial migration for the app `myproj`. So try this and let us know the result. – Avinash Kr Mallik Apr 27 '15 at 18:14

12 Answers12

41

Make sure that the migrations/ folder contains a __init__.py file

Lost half an hour over that.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
31

Deleting the migration directory is never a good idea, because Django then loses track of which migration has been applied and which not (and once an app is deployed somewhere it can become quite difficult to get things back in sync).

Disclaimer: whenever things like that occur it is best to backup the database if it contains anything valuable. If in early development it is not necessary, but once things on the backend get out of sync there is a chance of things getting worse. :-)


To recover, you could try resetting your models to match exactly what they were before you have added/removed the fields. Then you can run

$ python manage.py makemigrations myproj

which will lead to an initial migration (0001_initial...). Then you can tell Django to fake that migration, which means to tell it to set its internal counter to this 0001_initial:

With Django 1.7:

$ python manage.py migrate myproj

With Django >= 1.8:

$ python manage.py migrate myproj --fake-initial

Now, try to change your model and run makemigrations again. It should now create a 0002_foobar migration that you could run as expected.

sthzg
  • 5,514
  • 2
  • 29
  • 50
  • Thanks. Not deleting the folder is important to know. I got it working, but the --fake-initial option is not recognized. Any idea why? – max Apr 27 '15 at 18:40
  • Yes, my bad. `--fake-initial` was added in Django 1.8. From the docs: "The --fake-initial flag was added to migrate; previously, initial migrations were always automatically fake-applied if existing tables were detected." – sthzg Apr 27 '15 at 18:44
  • Updated the answer to be more precise on that. – sthzg Apr 27 '15 at 18:46
17

In my case, the migrations were not being reflected in mysql database. I manually removed the row of 'myapp'(in your case 'myproj') from the table 'django_migrations' in mysql database and ran the same commands again for migration.

pratikad
  • 1,239
  • 10
  • 8
11

Most of the above solutions would help in the issue, however, I wanted to point out another possible (albeit rare) possibility that the allow_migrate method of database router may be returning False when it should have returned None.

Django has a setting DATABASE_ROUTERS which will be used to determine which database to use when performing a database query.

From the docs:

if you want to implement more interesting database allocation behaviors, you can define and install your own database routers.

A database router class implements up to four methods:

  • db_for_read(model, **hints)
  • db_for_write(model, **hints)
  • allow_relation(obj1, obj2, **hints)
  • allow_migrate(db, app_label, model_name=None, **hints)

From the documentation:

allow_migrate(db, app_label, model_name=None, **hints)

Determine if the migration operation is allowed to run on the database with alias db. Return True if the operation should run, False if it shouldn’t run, or None if the router has no opinion.

It is possible that one of the database routers in sequence is returning False for the migration that you're trying to run, in which case the particular operation will not be run.

Community
  • 1
  • 1
Gaurav Toshniwal
  • 3,552
  • 2
  • 24
  • 23
  • I had to look through like ten overflow answers to find this. I renamed my app and got it one-off and this bit me. – tomaszps Apr 29 '21 at 02:12
6

I find Django migrations a bit of a mystery, and tend to prefer external tools (liquibase, for example).

However, I just ran into this "No migrations to apply" problem as well. I also tried removing the migrations folder, which doesn't help.

If you've already removed the migrations folder, here's an approach that worked for me.

First, generate the new "clean" migrations:

$ python manage.py makemigrations foo
Migrations for 'foo':
  dashboard/foo/migrations/0001_initial.py
    - Create model Foo
    - Create model Bar

Then look at the SQL and see if it looks reasonable:

$ python manage.py sqlmigrate foo 0001
BEGIN;
--
-- Create model Foo
--
CREATE TABLE "foo" ("id" serial NOT NULL PRIMARY KEY, ... "created_at" timestamp with time zone NOT NULL, "updated_at" timestamp with time zone NOT NULL);
CREATE INDEX "..." ON "foo" (...);
COMMIT;

Then apply execute that same SQL on your database.

I'm using Postgres but it will be similar for other engines.

One way is to write the content to a file:

$ python manage.py sqlmigrate foo 0001 > foo.sql
$ psql dbname username < foo.sql
BEGIN
CREATE TABLE
CREATE INDEX
COMMIT

Another is pipe the SQL directly:

$ python manage.py sqlmigrate foo 0001 | psql dbname username

Or copy and paste it, etc.

Andrew E
  • 7,697
  • 3
  • 42
  • 38
3
pip install django-extensions

and add this in the install app of settings.py

INSTALLED_APPS = [
    'django_extensions'
]

Then run

python ./manage.py reset_db

Then run migrations again

python manage.py makemigrations
python manage.py migrate

Now, run migrations for your installed apps

python manage.py makemigrations your_app_name
python manage.py migrtate your_app_name

Done! See Your Database...

ABcDexter
  • 2,751
  • 4
  • 28
  • 40
Haseeb
  • 2,039
  • 3
  • 11
  • 26
2

In addition to the other answers, make sure that in models.py, you have managed = True in each table's meta

1

You can remove your db

  • python manage.py makemigrations
  • python manage.py migrate
  • python manage.py migrate --run-syncdb

and see your data base this is working :)

Muhammadalive
  • 648
  • 5
  • 5
1

If you've deleted all migration files and tables, then do these steps:

  1. python manage.py makemigrations appname
  2. python manage.py migrate appname
  3. delete rows of that app from django_migrations table
  4. python manage.py migrate appname --fake-initial. It worked for me.
Batja
  • 51
  • 4
1

I was facing a similar issue when trying to migrate my models after creating it in models.py. The problem was that I had not registered the app name in the INSTALLED_APPS list in settings.py. The app name in my case was "core":

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'core'
]

After adding it to INSTALLED_APPS, the migrations worked like usual:

python manage.py makemigrations
python manage.py migrate
tdy
  • 36,675
  • 19
  • 86
  • 83
0

Similar to Andrew E above but with a few changes especially where you haven't deleted the migrations folder in your quest to resolve the issue

1 - In your intact migration folder just examine the 000*.py files counting from the highest down to initial.py till you find the one where your Model is defined, say 0002_entry.py

2 - python manage.py sqlmigrate app-name 0002 > 0002_sql.txt to capture the SQL commands

3 - Edit this file to ensure there are no hard CR/LFs and the ALTER, CREATE INDEX commands are each on own single line

4 - Log into your DB (I have Postgres) and run these commands

Sandy
  • 46
  • 3
0

In Database delete row myproj from the table django_migrations. Delete all migration files in the migrations folder. Then run python manage.py makemigrations and python manage.py migrate commands.

Javad
  • 2,033
  • 3
  • 13
  • 23