Come eliminare tutte le tabelle dal database con la CLI di manage.py in Django?


92

Come posso eliminare tutte le tabelle da un database utilizzando manage.py e la riga di comando? C'è un modo per farlo eseguendo manage.py con i parametri appropriati in modo da poterlo eseguire da un'applicazione .NET?

Risposte:


127

Per quanto ne so non esiste un comando di gestione per eliminare tutte le tabelle. Se non ti dispiace hackerare Python, puoi scrivere il tuo comando personalizzato per farlo. Potresti trovare l' sqlclearopzione interessante. La documentazione dice che ./manage.py sqlclear Stampa le istruzioni SQL DROP TABLE per i nomi di app specificati.

Aggiornamento : appropriandosi senza vergogna del commento di @Mike DeSimone sotto questa risposta per dare una risposta completa.

./manage.py sqlclear | ./manage.py dbshell

A partire da django 1.9 è ora ./manage.py sqlflush


sqlclear "stampa le istruzioni drop" ma come eseguirle in una singola chiamata da riga di comando
kmalmur

3
hai bisogno del nome dell'app come:./manage.py sqlclear myAppName | ./manage.py dbshell
Montaro

4
Questo non funziona affatto. sqlclear necessita di un nome per l'app. Sono su Django 1.8
Jonathan Hartley

Tieni solo presente che sqlflush non rilascia le tabelle, le tronca. Anche questa operazione probabilmente non funzionerà sul tuo DB postgresql a meno che tu non aggiunga la parola chiave CASCADE alla fine del comando truncate generato da sqlflush.
user3748764

35

Non esiste un comando di gestione Django nativo per eliminare tutte le tabelle. Entrambi sqlcleare resetrichiedono un nome per l'app.

Tuttavia, puoi installare Django Extensions che ti dà manage.py reset_db, che fa esattamente quello che vuoi (e ti dà accesso a molti più utili comandi di gestione).


@JulienGreard aggiornato. Grazie!
Anuj Gupta

3
Ho rinunciato a provare e ho usato questo.
laffuste

Questo ha funzionato per me, mentre nessuna delle risposte di grado superiore ha funzionato.
Jonathan Hartley

@AnujGupta anche spesso manage.py reset_db bisogno del flag `-c, --close-sessions` per chiudere le connessioni al database prima di rilasciare il database (solo PostgreSQL)
Valery Ramusik

34

Se stai utilizzando il pacchetto South per gestire le migrazioni del database (altamente consigliato), puoi semplicemente usare il ./manage.py migrate appname zerocomando.

Altrimenti, consiglierei il ./manage.py dbshellcomando, piping nei comandi SQL sull'input standard.


+1. Qualsiasi progetto Django non banale dovrebbe usare South. E una volta che usi South, migrare a Zero è un bel modo idiomatico per eliminare tutti i tavoli.
Manoj Govindan

Anche i banali progetti Django dovrebbero considerare South. Solo per abituare le persone alla migrazione dei database e così non apprendono cattive abitudini come cercare di scaricare, hackerare e ricaricare i dati manualmente o utilizzare il meccanismo dei dispositivi per migrare i dati.
Mike DeSimone

Uso South, ma non mi preoccupo di scrivere migrazioni inverse per ogni migrazione: non ultime migrazioni di dati. E non lo farei solo per poter usare l'opzione zero. Certamente un buon modo per testare che puoi / puoi / tornare a zero, se è importante per te. Eliminare tutti i tavoli mi sembra ragionevole.
tobych

26

python manage.py migrate <app> zero

sqlclear è stato rimosso da 1.9.

Le note di rilascio menzionano che è dovuto all'introduzione delle migrazioni: https://docs.djangoproject.com/en/1.9/releases/1.9/

Sfortunatamente non sono riuscito a trovare un metodo che funzioni su tutte le app contemporaneamente, né un modo integrato per elencare tutte le app installate dall'amministratore : come elencare tutte le app installate con manage.py in Django?

Correlati: come ripristinare le migrazioni in Django 1.7?


12

È meglio usare ./manage.py sqlflush | ./manage.py dbshellperché sqlclear richiede l'app per lo scaricamento.


7

modo semplice (?) per farlo da python (su mysql):

from django.db import connection

cursor = connection.cursor()
cursor.execute('show tables;')
parts = ('DROP TABLE IF EXISTS %s;' % table for (table,) in cursor.fetchall())
sql = 'SET FOREIGN_KEY_CHECKS = 0;\n' + '\n'.join(parts) + 'SET FOREIGN_KEY_CHECKS = 1;\n'
connection.cursor().execute(sql)

5

Se vuoi cancellare completamente il database e risincronizzarlo nello stesso passaggio, hai bisogno di qualcosa come il seguente. Combino anche l'aggiunta di dati di test in questo comando:

#!/usr/bin/env python

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "main.settings") # Replace with your app name.

from django.db import connection
from django.core.management import call_command
from django.conf import settings
# If you're using postgres you can't use django's sql stuff for some reason that I
# can't remember. It has to do with that autocommit thing I think.
# import psychodb2 as db

def recreateDb():
    print("Wiping database")
    dbinfo = settings.DATABASES['default']

    # Postgres version
    #conn = db.connect(host=dbinfo['HOST'], user=dbinfo['USER'],
    #                 password=dbinfo['PASSWORD'], port=int(dbinfo['PORT'] or 5432))
    #conn.autocommit = True
    #cursor = conn.cursor()
    #cursor.execute("DROP DATABASE " + dbinfo['NAME'])
    #cursor.execute("CREATE DATABASE " + dbinfo['NAME'] + " WITH ENCODING 'UTF8'") # Default is UTF8, but can be changed so lets be sure.

    # Mysql version:
    print("Dropping and creating database " + dbinfo['NAME'])
    cursor = connection.cursor()
    cursor.execute("DROP DATABASE " + dbinfo["NAME"] + "; CREATE DATABASE " + dbinfo["NAME"] + "; USE " + dbinfo["NAME"] + ";")
    print("Done")


if __name__ == "__main__":
    recreateDb();
    print("Syncing DB")
    call_command('syncdb', interactive=False)
    print("Adding test data")
    addTestData() # ...

Sarebbe bello poterlo fare cursor.execute(call_command('sqlclear', 'main'))ma call_commandstampa l'SQL su stdout invece di restituirlo come una stringa, e non riesco a elaborare il sql_deletecodice ...


Bello il USE DATABASEti consiglio di creare un pacchetto django-recreate-db con un comando di gestione che cambierà automaticamente in base alle impostazioni per passare da SQLite3 a PostGresql.
Natim

4

Ecco uno script di shell che ho finito per mettere insieme per affrontare questo problema. Spero che faccia risparmiare tempo a qualcuno.

#!/bin/sh

drop() {
    echo "Droping all tables prefixed with $1_."
    echo
    echo "show tables" | ./manage.py dbshell |
    egrep "^$1_" | xargs -I "@@" echo "DROP TABLE @@;" |
    ./manage.py dbshell
    echo "Tables dropped."
    echo
}

cancel() {
    echo "Cancelling Table Drop."
    echo
}

if [ -z "$1" ]; then
    echo "Please specify a table prefix to drop."
else
    echo "Drop all tables with $1_ prefix?"
    select choice in drop cancel;do
        $choice $1
        break
    done
fi

1

Usando Python per creare un comando flushproject, usi:

from django.db import connection
cursor = connection.cursor()
cursor.execute(“DROP DATABASE %s;”, [connection.settings_dict['NAME']])
cursor.execute(“CREATE DATABASE %s;”, [connection.settings_dict['NAME']])

La mia domanda, è come eseguire questa operazione se il database non esiste già?
Natim

Purtroppo qualsiasi ulteriore azione nello stesso script (ad es. Syncdb) genera errori "Nessun database selezionato".
Timmmm

Ha eseguito un comando flushdbe dopo aver lanciato un altro comando. se ne hai bisogno in un altro script, potresti usarecall_command
Natim

Io non seguo Sto già usando call_command. Stai dicendo che dovrei farlo call_command("flushdb")prima call_command("syncdb")?
Timmmm

Non funziona Stesso errore. L'errore è "Nessun database selezionato", quindi non è possibile eseguire alcun SQL. Trovato la soluzione: vedi la mia altra risposta.
Timmmm

1

Il comando ./manage.py sqlclearo ./manage.py sqlflushsembra cancellare la tabella e non eliminarli, tuttavia se vuoi eliminare il database completo prova questo:manage.py flush .

Attenzione: questo cancellerà completamente il tuo database e perderai tutti i tuoi dati, quindi se non è importante vai avanti e provalo.


2
No, non è corretto. flush e sqlflush è lo stesso, rimuove tutti i dati, ma non rilascia le tabelle. sqlflush visualizza sql, ma non lo esegue, flush lo esegue senza visualizzarlo.
Moulde

1

Ecco un esempio di Makefile per fare alcune cose carine con più file di impostazioni:

test:
    python manage.py test --settings=my_project.test

db_drop:
    echo 'DROP DATABASE my_project_development;' | ./manage.py dbshell
    echo 'DROP DATABASE my_project_test;' | ./manage.py dbshell

db_create:
    echo 'CREATE DATABASE my_project_development;' | ./manage.py dbshell
    echo 'CREATE DATABASE my_project_test;' | ./manage.py dbshell

db_migrate:
    python manage.py migrate --settings=my_project.base
    python manage.py migrate --settings=my_project.test

db_reset: db_drop db_create db_migrate

.PHONY: test db_drop db_create db_migrate db_reset

Quindi puoi fare cose come: $ make db_reset


1

Questa risposta è per postgresql DB:

Esegui: echo 'drop di proprietà di some_user ' | ./manage.py dbshell

NOTA: some_user è il nome dell'utente che utilizzi per accedere al database, vedi file settings.py:

default_database = {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'somedbname',
    'USER': 'some_user',
    'PASSWORD': 'somepass',
    'HOST': 'postgresql',
    'PORT': '',
}

1

Se stai usando psql e hai installato django-more 2.0.0, puoi farlo

manage.py reset_schema


0

Ecco una versione della migrazione a sud della risposta di @ peter-g. Spesso giocherello con sql grezzo, quindi questo è utile come 0001_initial.py per qualsiasi app confusa. Funzionerà solo su DB che supportano SHOW TABLES(come mysql). Sostituisci qualcosa come SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';se usi PostgreSQL. Inoltre, faccio spesso questa stessa identica cosa sia per l' forwardse backwardsmigrazioni.

from south.db import db
from south.v2 import SchemaMigration
from django.db.utils import DatabaseError
from os import path
from logging import getLogger
logger = getLogger(__name__)


class Migration(SchemaMigration):

    def forwards(self, orm):

        app_name = path.basename(path.split(path.split(path.abspath(__file__))[0])[0])
        table_tuples = db.execute(r"SHOW TABLES;")

        for tt in table_tuples:
            table = tt[0]
            if not table.startswith(app_name + '_'):
                continue
            try:
                logger.warn('Deleting db table %s ...' % table)
                db.delete_table(table)
            except DatabaseError:
                from traceback import format_exc
                logger.error("Error running %s: \n %s" % (repr(self.forwards), format_exc()))

Tuttavia, un collega / collaboratore mi ucciderebbe se sapessero che l'ho fatto.


0

C'è una risposta ancora più semplice se vuoi eliminare TUTTE le tue tabelle. Basta andare nella cartella contenente il database (che potrebbe essere chiamato miodatabase.db) e fare clic con il pulsante destro del mouse sul file .db e premere "elimina". Modo vecchio stile, lavoro sicuro.


1
Solo per database sqlite però :-)
vinto il

0

Elimina tutte le tabelle e le ricrea:

python manage.py sqlclear app1 app2 appN | sed -n "2,$p" | sed -n "$ !p" | sed "s/";/" CASCADE;/" | sed -e "1s/^/BEGIN;/" -e "$s/$/COMMIT;/" | python manage.py dbshell
python manage.py syncdb

Spiegazione:

manage.py sqlclear - "stampa le istruzioni SQL DROP TABLE per i nomi app specificati"

sed -n "2,$p" - afferra tutte le linee tranne la prima

sed -n "$ !p" - afferra tutte le linee tranne l'ultima

sed "s/";/" CASCADE;/" - sostituisce tutti i punti e virgola (;) con (CASCADE;)

sed -e "1s/^/BEGIN;/" -e "$s/$/COMMIT;/" - inserisce (BEGIN;) come primo testo, inserisce (COMMIT;) come ultimo testo

manage.py dbshell - "Esegue il client della riga di comando per il motore di database specificato nelle impostazioni ENGINE, con i parametri di connessione specificati nelle impostazioni USER, PASSWORD, ecc."

manage.py syncdb - "Crea le tabelle del database per tutte le app in INSTALLED_APPS le cui tabelle non sono già state create"

Dipendenze:


Crediti:

@Manoj Govindan e @Mike DeSimone per sqlclear convogliati su dbshell

@jpic per "sed" s / "; /" CASCADE; / "'


0

utilizzare il comando "python manage.py sqlflush" in Windows 10 per gli altri digitare manage.py


cosa vuoi dire??
tannu yadav

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.