Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

South: how to revert migrations in production server?

I want to revert my last migration (0157) by running its Migration.backwards() method. Since I am reverting the migration in production server I want to run it automatically during code deployment. Deployment script executes these steps:

  1. Pull code changes
  2. Run migrations: manage.py migrate <app>
  3. Refresh Apache to use newest code: touch django.wsgi

If I could, I would create new migration file which would tell South to backward migrate to 0156:

migrations/0158_backward__migrate_to_0156.py

This commited migration would be deployed to production and executed during manage.py migrate <app> command. In this case I wouldn't have to execute backward migration by hand, like suggested in these answers.

Lets say, I have created two data migrations, first for user's Payment, second for User model. I have implemented backwards() methods for both migrations in case I'd have to revert these data migrations. I've deployed these two migrations to production. And suddenly find out that Payment migration contains an error. I want to revert my two last data migrations as fast as possible. What is the fastest safe way to do it?

like image 327
niekas Avatar asked Dec 23 '13 17:12

niekas


People also ask

How do you reset migrations?

Reset the Whole Database in Django sqlite3 and then delete all the migrations folders inside all the apps. After deleting the migrations folders, we can remake the migrations and migrate them using two commands; namely, python manage.py makemigrations and python manage.py migrate .


2 Answers

Since I am reverting the migration in production server I want to run it automatically during code deployment.

IMHO the safest path is

  1. run manage.py migrate <app> (i.e. apply all existing migrations, i.e. up to 0156)
  2. undo the changes in your model
  3. run manage.py schemamigration <app> --auto

This will create a new migration 0157 that effectively reverts the previous migration 0156. Then simply apply the new migration by running manage.py migrate <app> again. As I understand, your code deployment will just do that.

like image 68
miraculixx Avatar answered Nov 02 '22 04:11

miraculixx


Apparently the codeline has migrations up to #157 and now the developer decided that the last one was not a good idea after all. So the plan is to go back to #156.

Two scenarios:

(a) migration #157 was not released or deployed anywhere yet. Simply revert the last change from models.py and delete migration #157.py from the source archive. Any deployment will take the system to level 156; "157 was never there".

(b) there have been deployments of the latest software with migration #157. In this case the previous strategy will obviously not work. So you need to create a migration #158 to undo #157. Revert the change in models.py and run

django manage.py migrate <app> 0157
django manage.py schemamigration <app> --auto

This will auto-generate a new migration #158, which will contain the inverse schema migration compared to #157.

If schemamigration is giving trouble because of django Model validation (something that can happen if you have custom validators which check stuff outside the ORM box), I suggest the following workaround:

<django project>/<app>/management/commands/checkmigrations.py

from south.management.commands import schemamigration
class Command(schemamigration.Command):
    requires_model_validation = False
    help = "schemamigration without model validation"

This command becomes available in manage.py:

django manage.py checkmigrations <app> --auto
like image 24
Freek Wiekmeijer Avatar answered Nov 02 '22 03:11

Freek Wiekmeijer