Comment supprimer toutes les tables de la base de données avec la CLI manage.py dans Django?

92

Comment supprimer toutes les tables d'une base de données à l'aide de manage.py et de la ligne de commande? Existe-t-il un moyen de le faire en exécutant manage.py avec les paramètres appropriés afin que je puisse l'exécuter à partir d'une application .NET?

kmalmur
la source

Réponses:

127

Autant que je sache, il n'y a pas de commande de gestion pour supprimer toutes les tables. Si cela ne vous dérange pas de pirater Python, vous pouvez écrire votre propre commande personnalisée pour le faire. Vous pouvez trouver l' sqlclearoption intéressante. La documentation indique que ./manage.py sqlclear Imprime les instructions SQL DROP TABLE pour le (s) nom (s) d'application donné (s).

Mise à jour : S'approprier sans vergogne le commentaire de @Mike DeSimone sous cette réponse pour donner une réponse complète.

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

Depuis django 1.9 c'est maintenant ./manage.py sqlflush

Manoj Govindan
la source
sqlclear "affiche les instructions drop" mais comment les exécuter en un seul appel en ligne de commande
kmalmur
3
vous avez besoin du nom de l'application comme:./manage.py sqlclear myAppName | ./manage.py dbshell
Montaro
4
Cela ne fonctionne pas du tout. sqlclear a besoin d'un nom d'application. Je suis sur Django 1.8
Jonathan Hartley
1
Sachez simplement que sqlflush ne supprime pas les tables, il les tronque. De plus, cette opération ne fonctionnera probablement pas sur votre base de données postgresql, sauf si vous ajoutez le mot-clé CASCADE à la fin de la commande truncate générée par sqlflush.
user3748764
35

Il n'y a pas de commande de gestion native de Django pour supprimer toutes les tables. Les deux sqlclearet resetnécessitent un nom d'application.

Cependant, vous pouvez installer Django Extensions qui vous donne manage.py reset_db, qui fait exactement ce que vous voulez (et vous donne accès à de nombreuses commandes de gestion plus utiles).

Anuj Gupta
la source
@JulienGreard Mis à jour. Merci!
Anuj Gupta
3
J'ai renoncé à essayer et utilisé cela.
laffuste
Cela a fonctionné pour moi, alors qu'aucune des réponses les mieux classées n'a fonctionné.
Jonathan Hartley
@AnujGupta a également souvent manage.py reset_dbbesoin de l'indicateur `-c, --close-sessions` pour fermer les connexions à la base de données avant de supprimer la base de données (PostgreSQL uniquement)
Valery Ramusik
34

Si vous utilisez le package South pour gérer les migrations de bases de données (fortement recommandé), vous pouvez simplement utiliser la ./manage.py migrate appname zerocommande.

Sinon, je recommanderais la ./manage.py dbshellcommande, piping dans les commandes SQL sur l'entrée standard.

Mike DeSimone
la source
+1. Tout projet Django non trivial doit utiliser South. Et une fois que vous utilisez South, migrer vers Zero est une manière idiomatique intéressante de supprimer toutes les tables.
Manoj Govindan
Même les projets Django triviaux devraient considérer South. Juste pour habituer les gens à migrer des bases de données, et pour qu'ils n'apprennent pas de mauvaises habitudes comme essayer de vider, pirater et recharger les données à la main, ou utiliser le mécanisme des fixtures pour migrer les données.
Mike DeSimone
J'utilise South, mais je ne prends pas la peine d'écrire des migrations inversées pour chaque migration: notamment des migrations de données. Et je ne ferais pas cela juste pour pouvoir utiliser l'option zéro. Certainement un bon moyen de tester que vous / pouvez / revenir à zéro, si cela est important pour vous. Abandonner toutes les tables me semble raisonnable.
tobych
26

python manage.py migrate <app> zero

sqlclear a été supprimé de 1.9.

Les notes de publication mentionnent que cela est dû à l'introduction de migrations: https://docs.djangoproject.com/en/1.9/releases/1.9/

Malheureusement, je n'ai pas trouvé de méthode qui fonctionne sur toutes les applications à la fois, ni de moyen intégré de répertorier toutes les applications installées depuis l'administrateur: Comment répertorier toutes les applications installées avec manage.py dans Django?

En relation: Comment réinitialiser les migrations dans Django 1.7?

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
12

Il est préférable de l'utiliser ./manage.py sqlflush | ./manage.py dbshellcar sqlclear nécessite l'application pour vider.

FeroxTL
la source
7

façon simple (?) de le faire à partir de python (sur 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)
Lemanyk
la source
5

Si vous souhaitez effacer complètement la base de données et la resynchroniser de la même manière, vous avez besoin de quelque chose comme ce qui suit. Je combine également l'ajout de données de test dans cette commande:

#!/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() # ...

Ce serait bien de pouvoir le faire cursor.execute(call_command('sqlclear', 'main'))mais call_commandimprime le SQL sur stdout plutôt que de le renvoyer sous forme de chaîne, et je ne peux pas travailler sur le sql_deletecode ...

Timmmm
la source
Nice , le USE DATABASEJe vous recommandons de créer un package django-Recréer-db avec une commande de gestion qui basculera automatiquement en fonction des paramètres pour basculer entre les SQLite3 et Postgresql.
Natim
4

Voici un script shell que j'ai fini par assembler pour résoudre ce problème. J'espère que cela fera gagner du temps à quelqu'un.

#!/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
Peter G
la source
1

En utilisant Python pour créer une commande flushproject, vous utilisez:

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']])
Natim
la source
Ma question est de savoir comment procéder si la base de données n'existe pas déjà?
Natim
Malheureusement, toute action supplémentaire dans le même script (par exemple syncdb) entraîne des erreurs "Aucune base de données sélectionnée".
Timmmm
Il a fait une commande flushdbet après j'ai lancé une autre commande. si vous en avez besoin dans un autre script, vous pouvez utilisercall_command
Natim
Je ne suis pas. J'utilise déjà call_command. Vous dites que je devrais faire call_command("flushdb")avant call_command("syncdb")?
Timmmm
Ça ne marche pas. Même erreur. L'erreur est "Aucune base de données sélectionnée", vous ne pouvez donc exécuter aucun SQL. J'ai trouvé la solution: voir mon autre réponse.
Timmmm
1

La commande ./manage.py sqlclearou ./manage.py sqlflushsemble effacer la table et ne pas les supprimer, si vous souhaitez supprimer la base de données complète , essayez ceci: manage.py flush.

Attention: cela supprimera complètement votre base de données et vous perdrez toutes vos données, donc si cela n'est pas important, essayez-le.

iyogeshjoshi
la source
2
Non, c'est incorrect. flush et sqlflush sont les mêmes, il supprime toutes les données, mais ne supprime pas les tables. sqlflush affiche le sql, mais ne l'exécute pas, flush l'exécute sans l'afficher.
Moulde
1

Voici un exemple de Makefile pour faire de belles choses avec plusieurs fichiers de paramètres:

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

Ensuite, vous pouvez faire des choses comme: $ make db_reset

daino3
la source
1

Cette réponse est pour postgresql DB:

Exécuter: echo 'drop appartenant à some_user ' | ./manage.py dbshell

REMARQUE: some_user est le nom de l'utilisateur que vous utilisez pour accéder à la base de données, voir le fichier settings.py:

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

Si vous utilisez psql et que django-more 2.0.0 est installé, vous pouvez faire

manage.py reset_schema

Alice Purcell
la source
0

Voici une version de migration vers le sud de la réponse de @ peter-g. Je joue souvent avec le sql brut, donc cela est pratique sous le nom 0001_initial.py pour toutes les applications déroutées. Cela ne fonctionnera que sur les bases de données prenant en charge SHOW TABLES(comme mysql). Remplacez quelque chose comme SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';si vous utilisez PostgreSQL. De plus, je fais souvent exactement la même chose pour les migrations forwardset backwards.

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()))

Cependant, mes collègues / cocodeurs me tueraient s'ils savaient que je faisais ça.

plaques de cuisson
la source
0

Il existe une réponse encore plus simple si vous souhaitez supprimer TOUTES vos tables. Vous allez simplement dans votre dossier contenant la base de données (qui peut être appelé mydatabase.db) et cliquez avec le bouton droit sur le fichier .db et appuyez sur «supprimer». Manière à l'ancienne, sûr de travailler.

Rock Lee
la source
1
Seulement pour les bases de données sqlite cependant :-)
winwaed
0

Supprime toutes les tables et les recrée:

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

Explication:

manage.py sqlclear - "imprime les instructions SQL DROP TABLE pour le (s) nom (s) d'application donné (s)"

sed -n "2,$p" - attrape toutes les lignes sauf la première ligne

sed -n "$ !p" - attrape toutes les lignes sauf la dernière ligne

sed "s/";/" CASCADE;/" - remplace tous les points-virgules (;) par (CASCADE;)

sed -e "1s/^/BEGIN;/" -e "$s/$/COMMIT;/" - insère (BEGIN;) comme premier texte, insère (COMMIT;) comme dernier texte

manage.py dbshell - "Exécute le client de ligne de commande pour le moteur de base de données spécifié dans votre paramètre ENGINE, avec les paramètres de connexion spécifiés dans vos paramètres USER, PASSWORD, etc."

manage.py syncdb - "Crée les tables de base de données pour toutes les applications dans INSTALLED_APPS dont les tables n'ont pas déjà été créées"

Dépendances:


Crédits:

@Manoj Govindan et @Mike DeSimone pour sqlclear canalisés vers dbshell

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

Stephen Cernota
la source
0

utilisez la commande "python manage.py sqlflush" dans Windows 10 pour les autres tapez manage.py

tannu yadav
la source
ce que vous voulez dire??
tannu yadav
0

Je vous recommande d'installer django-extensions et d'utiliser la python manage.py reset_dbcommande. Il fait exactement ce que vous voulez.

Diego Aragão
la source