user85461
user85461

Reputation: 6640

Django: Remove all data from every table (but keep the tables themselves)

I'm trying to sync data between two django installations (production and testing). I'm doing this using ./manage.py dumpdata --natural on production, then ./manage.py loaddata into a freshly syncdb'ed database on testing.

Everything was working fine until I added a new custom permission. The production syncdb loaded this new permission in a different order (with different primary key) than a new syncdb on an empty database does. Consequently, it gets a different ID. So despite using natural keys, when I attempt to load the data, I'm getting this error when the first out-of-order permission object is loaded:

IntegrityError: duplicate key value violates unique constraint "auth_permission_content_type_id_codename_key"

The easiest way I can think of to fix this is to remove all data from every table in the testing installation -- that is, to use syncdb just to create tables, and not to also load initial data. But syncdb doesn't let you skip the initial data/signals step. Short of enumerating every model or table name explicitly, how can I remove all initial data after calling syncdb? Or is there a way to create just the empty tables without using syncdb?

./manage.py flush isn't what I'm after -- it reloads initial data and triggers syncdb signals.

Upvotes: 10

Views: 9387

Answers (2)

Alasdair
Alasdair

Reputation: 308779

For Django <= 1.4, you can use the reset management command.

./manage.py sqlreset myapp1 myapp2

Upvotes: 0

CraigTeegarden
CraigTeegarden

Reputation: 8251

According to the help for flush command (I'm using Django 1.3.1) the SQL that is executed is the same SQL obtained from ./manage.py sqlflush, and then the initial data fixtures is reinstalled.

$ python manage.py help flush 
Usage: manage.py flush [options]

Executes ``sqlflush`` on the current database.

To get the same data wiping capabilities minus the fixture loading you can obtain the SQL by calling ./manage.py sqlflush and then execute that SQL using Django's built-in support for executing arbitrary SQL:

from django.core.management import call_command, setup_environ
from your_django_project import settings
setup_environ(settings)

from django.db import connection
from StringIO import StringIO

def main():
    # 'call' manage.py flush and capture its outputted sql
    command_output = StringIO()
    call_command("sqlflush", stdout=command_output)

    command_output.seek(0)
    flush_sql = command_output.read()

    # execute the sql
    # from: https://docs.djangoproject.com/en/dev/topics/db/sql/#executing-custom-sql-directly
    cursor = connection.cursor()
    cursor.execute(flush_sql)

    print "db has been reset"

if __name__ == '__main__':
    main()

This has the added benefit that you can modify the SQL from ./manage.py sqlflush before execution to avoid wiping tables that you might want to leave intact.

Also, according to the current Django docs, in Django 1.5 a new parameter ./manage.py flush --no-initial-data will reset the data and not load the initial data fixture.

Upvotes: 9

Related Questions