62
votes

(I know there is a title the same as this, but the question is different).

I have managed to get my development machine migrations and production migrations out of sync.

I have a Django app which was using South. I had my own workflow that worked fine (it probably wasn't the correct way to do things, but I had no problems with it).

Basically I have a script that copies the production database dump to my development machine. It also copied the migration files. That way the two were in synch, and I could run South commands as normal.

Now I have upgraded to 1.7, and started using migrations. When I use my previous workflow (copy database dump, and migration files from production), it is not detecting changes on my development machine.

I have read through the migrations document, and I see that the correct way to use it is to

  1. run "make migrations" and "migrate" on my development machine.
  2. run "migrate" on my devlopemnt machine to actually make the database changes
  3. Copy changes over, including migration files.
  4. run "migrate" on the production machine. (without the "makemigrations" step)

Anyway. It is all a mess now. I would like to "reset" my migrations and start from scratch, doing things properly from now on.

What do I need to do?

  1. Delete the contents of the migration table (on both machines)?
  2. Delete the contents of the migration folder? (Including the init.py file).
  3. Start the migrations as per the documentation for a new one.

Have I missed anything? Is there a reason why copying everything from production(database and migration files) doesn't detect any changes on my development machine afterwards

8
Just delete the migrations folder and make new ones...rnevius
Done that, it doesn't detect changes. Plus you need to keep the database table in sync with the migrations folder. I was wondering if there is anything else.wobbily_col

8 Answers

98
votes

I would just do the following on both the environments (as long as the code is the same)

  1. Delete your migrations folder
  2. DELETE FROM django_migrations WHERE app = <your app name> . You could alternatively just truncate this table.
  3. python manage.py makemigrations
  4. python manage.py migrate --fake

After this all your changes should get detected across environments.

63
votes

Run

python manage.py migrate your_app zero

This will drop all tables from your_app

If you want, since you said you want to start over, you can delete your migrations folder, or maybe rename the folder, create a new migrations folder and run

python manage.py makemigrations your_app
python manage.py migrate your_app

Just like south, you can always go back and forth...

# Go to the first migration
python manage.py migrate your_app 0001

# Go to the third migration
python manage.py migrate your_app 0003

So imagine that your 4th migration is a mess... you can always migrate to the 3rd, remove the 4th migration file and do it again.

Note:

This one of the reasons your models should be in different apps. Say you have 2 models : User and Note. It's a good practice to create 2 apps: users and notes so the migrations are independent from each other.

Try not use a single application for all your models

28
votes

A minor variation on harshil's answer:

$ manage.py migrate --fake <appname> zero
$ rm -rf migrations
$ manage.py makemigrations <appname>
$ manage.py migrate --fake <appname>

This will ...

  • pretend to rollback all of your migrations without touching the actual tables in the app
  • remove your existing migration scripts for the app
  • create a new initial migration for the app
  • fake a migration to the initial migration for the app
2
votes

if you want to totally reset the database and the schema then put the code in any app like this

app/management/commands/resetdb.py

import os
import glob
import shutil
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from django.db import connection


class Command(BaseCommand):
    help = 'Resets the database'

    def handle(self, *args, **options):
        dbname = settings.DATABASES["default"]["NAME"]
        with connection.cursor() as cursor:
            cursor.execute("DROP DATABASE %s" % dbname)
            cursor.execute("CREATE DATABASE %s" % dbname)

        base = str(settings.BASE_DIR)
        migrations = glob.glob(os.path.join(base, "*", "migrations"))

        for migration in migrations:
            shutil.rmtree(migration)

        apps = [migration.split("\\")[-2] for migration in migrations]
        for app in apps:
            os.system("python manage.py makemigrations %s" % app)
        os.system("python manage.py migrate")

now reset it using :

python manage.py resetdb

this will

  • drop the database
  • delete the migrations folders
  • make migrations
  • migrate the fresh db
2
votes

I had a similar issue to this but when testing some of these same solutions using python manage.py showmigrations I noticed I got the same error.

Eventually I found this post which helped me realize I was overcomplicating things and essentially had two User models defined.

2
votes

To reset all migrations and start all over, you can run the following:

1. Reset all migration

python manage.py migrate <app_name> zero

ℹ️ If this is causing you issues you can add the --fake flag to the end of the command.

2. Create the migration

python manage.py makemigrations <app_name>

ℹ️ Only do this step if you deleted or altered the migrations files

3. Migrate

python manage.py migrate <app_name>

⚠️ if you added the --fake command to step # 1 you will need to add --fake-initial to the migrate command so python manage.py migrate <app_name> --fake-initial

1
votes

So this solution worked for me today.

  1. Drop the django migrations table called "django_migrations" (No need to drop the whole database - just the migration table.)

  2. Deleted all migrations files (e.g. 0002_auto.py, etc) from all your apps, leave the __init__.py files. You can use this code from Ahmed Bouchefra:

    find . -path "/migrations/.py" -not -name "init.py" -delete

    find . -path "/migrations/.pyc" -delete

(This find and delete code works only for linux. For Windows you have to delete your files manually.)

  1. Now run the following commands:

    python manage.py makemigrations
    
    python manage.py migrate --fake
    

django will create a new migration table and fake the initial migration into the table without touching your existing data. Enjoy.

0
votes

This works for me

Step1:
delete all "migrations" folders in all apps

Step2:
create a brand new app.
python manage.py justTestApp.
Copy the new "migrations" folder of the new app to all apps

Step3:
delete the "db.sqlite3" file.
delete the "justTestApp" folder

Step4:
python manage.py makemigrations
python manage.py migrate