6

How do I delete all the data in the database for on Django app? In previous version manage.py reset APPNAME did the job, but that's been deprecated.

What are we supposed to do now if we want to delete all the data from an app using the command line?

Ashwin Balamohan
  • 3,303
  • 2
  • 25
  • 47
Amandasaurus
  • 58,203
  • 71
  • 188
  • 248

5 Answers5

15

reset and sqlreset were both just wrappers around other management commands. sqlreset in particular can be duplicate by simply running:

python manage.py sqlclear myapp
python manage.py sqlall myapp

reset only served to automatically run the result of sqlreset on the database. Personally, I think removing that is a fantastic idea. Still, if you want similar functionality, you can just pipe the output to your database's shell commands.

For PostgreSQL, for example:

python manage.py sqlclear myapp | psql mydatabase
python manage.py sqlall myapp | psql mydatabase
Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • 3
    Why is this a good idea when you need to write much more code instead of one line? What was the disadvantage of that wrapper? – JasonTS Oct 04 '13 at 07:13
  • 1
    It's an issue of being explicit about doing potentially destructive things. It's not a good idea to just automatically run output SQL against your database. You *assume* that the command worked correctly, but what if it didn't? The smart thing is to look at the generated code first. If you truly don't care and/or implicitly trust Django to never screw up, then you can pipe the result, but now you are making an explicit choice to do so. – Chris Pratt Oct 04 '13 at 14:13
8

If you want single command that should work with most database types you can pipe the drop table statements, that sqlclear generates, to dbshell

python manage.py sqlclear myapp | python manage.py dbshell

Ossi
  • 121
  • 1
  • 3
  • If using south, create an initial commit again using schemamigration and then use ./manage.py migrate worksheets --delete-ghost-migrations to migrate without errors – radtek Sep 12 '14 at 17:15
5
from django.contrib.contenttypes.models import ContentType
for ct in ContentType.objects.all()
    ct.model_class().objects.all().delete()
Goin
  • 3,856
  • 26
  • 44
2

Now that Django integrates migrations by default, you first need to make migrations for your app are first unapplied then deleted.

Here is the command line that works at least with Django 1.8 (replacing by the application you want to delete all associated data and:

# First, update the DB so it thinks no migrations were applied to the app
python manage.py migrate --fake <app_name> zero

# Erase all migrations in the app folder
rm -r "<app_name>/migrations/*"

# Erase the application tables
python manage.py sqlclear <app_name> | python manage.py dbshell

# Recreate the app tables, that will be empty
python manage.py makemigrations <app_name>
python manage.py migrate <app_name>
Ad N
  • 7,930
  • 6
  • 36
  • 80
0

DIY

If you want to do that from the command line, create the following custom command:

from django.core.management.base import AppCommand, CommandError
from django.utils.six.moves import input
from django.db import DEFAULT_DB_ALIAS, connections

class Command(AppCommand):
    help = (
        'Removes ALL DATA related to the given app from the database '
        'by calling model.objects.all().delete() for all app models. '
        'This also removes related data in other apps via cascade.'
    )

    def add_arguments(self, parser):
        super(Command, self).add_arguments(parser)
        parser.add_argument(
            '--noinput', '--no-input',
            action='store_false', dest='interactive', default=True,
            help='Tells Django to NOT prompt the user for input of any kind.',
        )
        parser.add_argument(
            '--database', action='store', dest='database', default=DEFAULT_DB_ALIAS,
            help='Nominates a database to reset. Defaults to the "default" database.',
        )

    def handle_app_config(self, app_config, **options):
        app_label = app_config.label
        database = options['database']
        interactive = options['interactive']
        db_name = connections[database].settings_dict['NAME']

        confirm = (ask_confirmation(app_label, db_name)
                if interactive else 'yes')

        if confirm == 'yes':
            for model in app_config.get_models():
                model.objects.using(database).all().delete()
            self.stdout.write('Reset done.\n')
        else:
            self.stdout.write("Reset cancelled.\n")

def ask_confirmation(app_label, db_name):
    return input("""You have requested a reset of the application {app_label}.
This will IRREVERSIBLY DESTROY all data related to the app currently in
the {db_name} database, and return each table to empty state.
Are you sure you want to do this?
    Type 'yes' to continue, or 'no' to cancel: """.format(**locals()))

Copy it to app/management/commands folder in any of your apps folders and run it with

./manage.py app_db_tables_reset any_installed_app_name

Ready-made package

The command is available in the django_commands package, you can install it with

pip install git+http://github.com/mrts/django-commands.git

and add it to INSTALLED_APPS to activate the command.

Tested with Django 1.9, it may or may not work with 1.8.

mrts
  • 16,697
  • 8
  • 89
  • 72