How to simplify migrations in Django 1.7?

2019-01-07 04:55发布

问题:

There are already similar questions for South, but I have started my project with Django 1.7 and am not using South.

During development a lot of migrations have been created, however the software is not yet delievered and there exists no database that must be migrated. Therefore I would like to reset the migrations as if my current model was the original one and recreate all databases.

What is the recommended way to do that?

EDIT: As of Django 1.8 there is a new command named squashmigrations which more or less solves the problem described here.

回答1:

In the Django 1.7 version of migrations the reset functionality that used to be in South has been dropped in favor of new functionality for 'squashing' your migrations. This is supposed to be a good way to keep the number of migrations in check.

https://docs.djangoproject.com/en/dev/topics/migrations/#squashing-migrations

If you still want to really start from scratch i assume you still could by emptying the migrations table and removing the migrations after which you would run makemigrations again.



回答2:

I got this. I just figured this out and it is good.

  • First, to clear migrations table:

    ./manage.py migrate --fake <app-name> zero
    
  • Remove app-name/migrations/ folder or contents.

  • Make the migrations:

    ./manage.py makemigrations <app-name>
    
  • Finally tidy up your migrations without making other database changes:

    ./manage.py migrate --fake <app-name>
    


回答3:

I just had the same problem. Here's my workaround.

#!/bin/sh
echo "Starting ..."

echo ">> Deleting old migrations"
find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc"  -delete


# Optional
echo ">> Deleting database"
find . -name "db.sqlite3" -delete

echo ">> Running manage.py makemigrations"
python manage.py makemigrations

echo ">> Running manage.py migrate"
python manage.py migrate

echo ">> Done"

The find command: http://unixhelp.ed.ac.uk/CGI/man-cgi?find



回答4:

Assuming this is your project structure,

project_root/
    app1/
        migrations/
    app2/
        migrations/
    ...
    manage.py
    remove_migrations.py

you can run the script remove_migrations.py from the the place indicated above to delete all migrations files.

#remove_migrations.py
"""
Run this file from a Django =1.7 project root. 
Removes all migration files from all apps in a project.
""" 
from unipath import Path

this_file = Path(__file__).absolute()
current_dir = this_file.parent
dir_list = current_dir.listdir()

for paths in dir_list:
    migration_folder = paths.child('migrations')
    if migration_folder.exists():
        list_files = migration_folder.listdir()
        for files in list_files:
            split = files.components()
            if split[-1] != Path('__init__.py'):
                files.remove()

Manually deleting can be tiring if you have an elaborate project. This saved me a lot of time. Deleting migration files is safe. I have done this an umpteenth number of times without facing any problems...yet.

However when I deleted the migrations folder, makemigrations or migrate did not create the folder back for me. The script makes sure that the migration folder with its __init__.py stays put, only deleting the migration files.



回答5:

  1. Delete files: delete_migrations.py (in root of prj):
import os

for root, dirs, files in os.walk(".", topdown=False):
  for name in files:
      if '/migrations' in root and name != '__init__.py':
          os.remove(os.path.join(root, name))
  1. DELETE FROM django_migrations Where app in ('app1', 'app2');

  2. ./manage.py makemigrations

  3. ./manage.py migrate --fake

OR, you can write migration from this all



回答6:

I try different commands and some of the answers help me. Only this sequence in my case fixed both broken dependencies in migrations in MYAPP and clean all past migrations starting from scratch.

Before doing this ensure that database is already synced (e.g. do not add a new Model field here or change Meta options).

rm -Rf MYAPP/migrations/*
python manage.py makemigrations --empty MYAPP
python manage.py makemigrations
python manage.py migrate --fake MYAPP 0002

Where 0002 is the migration number returned by the last makemigrations command.

Now you can run makemigrations / migrate again normally because migration 0002 is stored but not reflected in the already-synced database.



回答7:

If you don't care about previous migrations, what about just removing all migrations in the migrations/ directory? you will start the migration sequence from scratch, taking your current model as reference as if you had written the whole model now.

If you don't trust me enought to remove, then try to move them away instead.



回答8:

A simple way is

Go to every app and delete the migration files.

Then go to the django-migrtaions table in the database and truncate it(delete all entries).

After that you can create migrations once again.



回答9:

cd to src directory cd /path/to/src

delete migration directories rm -rf your_app/migrations/

note that this should be done for each app separately

migrate python3.3 manage.py migrate

if you wish to start again python3.3 manage.py makemigrations your_app



回答10:

If you're in development mode and you just want to reset everything (database, migrations, etc), I use this script based on Abdelhamid Ba's answer. This will wipe the tables of the database (Postgres), delete all migration files, re-run the migrations and load my initial fixtures:

#!/usr/bin/env bash
echo "This will wipe out the database, delete migration files, make and apply migrations and load the intial fixtures."

while true; do
    read -p "Do you wish to continue?" yn
    case $yn in
        [Yy]* ) make install; break;;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac
done

echo ">> Deleting old migrations"
find ../../src -path "*/migrations/*.py" -not -name "__init__.py" -delete

# Optional
echo ">> Deleting database"
psql -U db_user -d db_name -a -f ./reset-db.sql

echo ">> Running manage.py makemigrations and migrate"
./migrations.sh

echo ">> Loading initial fixtures"
./load_initial_fixtures.sh

echo ">> Done"

reset-db.sql file:

DO $$ DECLARE
    r RECORD;
BEGIN
    -- if the schema you operate on is not "current", you will want to
    -- replace current_schema() in query with 'schematodeletetablesfrom'
    -- *and* update the generate 'DROP...' accordingly.
    FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
        EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE';
    END LOOP;
END $$;

migration.sh file:

#!/usr/bin/env bash
cd ../../src
./manage.py makemigrations
./manage.py migrate

load_initial_fixtures.sh file:

#!/usr/bin/env bash
cd ../../src
./manage.py loaddata ~/path-to-fixture/fixture.json

Just be sure to change the paths to corresponds to your app. I personally have these scripts in a folder called project_root/script/local, and django's sources are in project_root/src.



回答11:

After deleting each "migrations" folder in my app (manually), I ran:

./manage.py dbshell
delete from django_migrations;

Then I thought I could just do ./manage.py makemigrations to regenerate them all. However, no changes were detected. I then tried specifying one app at a time: ./manage.py makemigrations foo, ./manage.py makemigrations bar. However, this resulted in circular dependencies that could not be resolved.

Finally, I ran a single makemigrations command that specified ALL of my apps (in no particular order):

./manage.py makemigrations foo bar bike orange banana etc

This time, it worked - circular dependencies were automatically resolved (it created additional migrations files where necessary).

Then I was able to run ./manage.py migrate --fake and was back in business.