16

I would like to know whats the cleanest way to remove all tables for a removed app using Django migrations. If for example I install a new package, I add the app to my settings.py and I do a manage.py makemigrations and a manage.py migrate; when then I decide that I don't want to use this package and I remove it from my settings.py, the command manage.py makemigrations will tell me "no changes detected" and so manage.py migrate will do nothing, but I need to remove the tables that this removed app had created.

I expected Django migrations to handle this so if I remove a app it would also create migrations to remove all the necesary tables.

diegopau
  • 1,324
  • 10
  • 22

3 Answers3

19

you'd have to be careful with this one, make sure you understand the operations being reversed when you do it, but something like this should work:

manage.py migrate <app_name> zero

obviously you have to do this before removing it from your settings and such so migrations are discoverable.

edit: this has slowly been receiving a few upvotes - I figured I'd direct everybody towards the appropriate documentation, in particular:

Use the name zero to unapply all migrations for an app.

ara.hayrabedian
  • 458
  • 4
  • 14
3

First, comment out all the classes in your app's models.py. Then, create a new migration as you normally would, which will delete all the app's tables, and run it. Finally, remove the entire app and all references to it from your code base.

Cloud Artisans
  • 4,016
  • 3
  • 30
  • 37
  • This seems like a good solution, but makes more sense when the app is integrated in my project, in this case I am just installing a package in my virtualenv and linking it to my project adding it to my settings.py. I am new to Django so it might be something stupid I am not getting yet! – diegopau Feb 08 '15 at 14:37
  • 1
    To remove the entire app one can use "python manage.py migrate [app_name] zero" – potar Aug 04 '15 at 07:39
3

extending nachouve's answer to a proper django migration, you can use a RunSQL migration with all the DROP statements, see the django migration docs.

You can either put this in the app your about to delete or (if you've already deleted the app or it's installed so you can't edit it) in a different app.

For example to clean up after deleting django-user-accounts (which has poor coverage and is a liability):

from django.db import migrations

DROP_ACCOUNT_TABLES = """\
    DROP TABLE IF EXISTS account_account CASCADE;
    DROP TABLE IF EXISTS account_accountdeletion CASCADE;
    DROP TABLE IF EXISTS account_emailaddress CASCADE;
    DROP TABLE IF EXISTS account_emailconfirmation CASCADE;
    DROP TABLE IF EXISTS account_signupcode CASCADE;
    DROP TABLE IF EXISTS account_signupcoderesult CASCADE;
"""


class Migration(migrations.Migration):

    dependencies = [
        ('auth', '<< previous migations >>'),
    ]

    operations = [
        migrations.RunSQL(DROP_ACCOUNT_TABLES)
    ]
SColvin
  • 11,584
  • 6
  • 57
  • 71
  • 1
    This is my favorite solution but it still doesn't work if on other apps you have models that used to have foreign keys to models in the app to be removed. You'll get a NodeNotFoundError: `django.db.migrations.exceptions.NodeNotFoundError: Migration other_app.0001_initial dependencies reference nonexistent parent node (app_to_be_removed', u'0001_initial')`. Any ideas on how to avoid that? – Ariel Mar 04 '19 at 15:35