Jak usunąć wszystkie tabele z bazy danych za pomocą manage.py CLI w Django?


94

Jak usunąć wszystkie tabele z bazy danych za pomocą manage.py i wiersza poleceń? Czy istnieje sposób, aby to zrobić, uruchamiając manage.py z odpowiednimi parametrami, abym mógł to zrobić z aplikacji .NET?

Odpowiedzi:


128

O ile wiem, nie ma polecenia zarządzania, które usuwałoby wszystkie tabele. Jeśli nie masz nic przeciwko włamywaniu się do Pythona, możesz napisać własne niestandardowe polecenie, które to zrobi. Ta sqlclearopcja może być interesująca. Dokumentacja mówi, że ./manage.py sqlclear drukuje instrukcje SQL DROP TABLE dla podanych nazw aplikacji.

Aktualizacja : Bezwstydne zawłaszczenie komentarza @Mike DeSimone pod tą odpowiedzią, aby udzielić pełnej odpowiedzi.

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

Od django 1.9 jest teraz ./manage.py sqlflush


sqlclear "drukuje instrukcje drop", ale jak je wykonać w pojedynczym wywołaniu wiersza poleceń
kmalmur

3
potrzebujesz nazwy aplikacji, takiej jak:./manage.py sqlclear myAppName | ./manage.py dbshell
Montaro

4
To w ogóle nie działa. sqlclear potrzebuje nazwy aplikacji. Jestem na Django 1.8
Jonathan Hartley

1
Pamiętaj tylko, że sqlflush nie porzuca tabel, obcina je. Również ta operacja prawdopodobnie nie zadziała na twojej bazie danych postgresql, chyba że dodasz słowo kluczowe CASCADE na końcu komendy truncate wygenerowanej przez sqlflush.
user3748764

38

Nie ma natywnego polecenia zarządzania Django, które usuwałoby wszystkie tabele. Obie sqlcleari resetwymagają nazwy aplikacji.

Możesz jednak zainstalować rozszerzenia Django, które dają ci manage.py reset_dbdokładnie to, co chcesz (i dają dostęp do wielu bardziej przydatnych poleceń zarządzania).


@JulienGreard Zaktualizowano. Dzięki!
Anuj Gupta,

4
Zrezygnowałem z prób i wykorzystałem to.
laffuste

To zadziałało dla mnie, podczas gdy żadna z wyżej ocenionych odpowiedzi nie zadziałała.
Jonathan Hartley

@AnujGupta często manage.py reset_dbpotrzebuje również flagi `-c, --close-session`, aby zamknąć połączenia z bazą danych przed usunięciem bazy danych (tylko PostgreSQL)
Valery Ramusik

34

Jeśli używasz pakietu South do obsługi migracji bazy danych (wysoce zalecane), możesz po prostu użyć ./manage.py migrate appname zeropolecenia.

W przeciwnym razie poleciłbym ./manage.py dbshellpolecenie, przesyłając polecenia SQL na standardowe wejście.


+1. Każdy nietrywialny projekt Django powinien używać South. A kiedy użyjesz South, migracja do Zero jest przyjemnym idiomatycznym sposobem na usunięcie wszystkich tabel.
Manoj Govindan

Nawet trywialne projekty Django powinny rozważyć South. Tylko po to, aby przyzwyczaić ludzi do migracji baz danych i aby nie nauczyli się złych nawyków, takich jak ręczne zrzucanie, hakowanie i ponowne ładowanie danych lub używanie mechanizmu urządzeń do migracji danych.
Mike DeSimone

Używam South, ale nie zawracam sobie głowy pisaniem migracji zwrotnych dla każdej migracji: nie tylko migracji danych. I nie zrobiłbym tego tylko po to, aby użyć opcji zerowej. Z pewnością dobry sposób testowania, który możesz / możesz / cofnąć z powrotem do zera, jeśli jest to dla Ciebie ważne. Porzucenie wszystkich stołów wydaje mi się rozsądne.
tobych

26

python manage.py migrate <app> zero

sqlclear została usunięta z 1.9.

Uwagi do wydania wspominają, że jest to spowodowane wprowadzeniem migracji: https://docs.djangoproject.com/en/1.9/releases/1.9/

Niestety nie mogłem znaleźć metody, która działałaby na wszystkich aplikacjach jednocześnie, ani wbudowanego sposobu wyświetlania listy wszystkich zainstalowanych aplikacji od administratora: Jak wyświetlić listę wszystkich zainstalowanych aplikacji za pomocą manage.py w Django?

Powiązane: Jak zresetować migracje w Django 1.7?


12

Lepiej jest używać, ./manage.py sqlflush | ./manage.py dbshellponieważ sqlclear wymaga aplikacji do opróżnienia.


7

prosty (?) sposób na zrobienie tego z pythona (na 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

Jeśli chcesz całkowicie wyczyścić bazę danych i ponownie zsynchronizować ją w tym samym czasie, potrzebujesz czegoś podobnego do następującego. Łączę też dodawanie danych testowych w tym poleceniu:

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

Byłoby miło móc to zrobić, cursor.execute(call_command('sqlclear', 'main'))ale call_commanddrukuje SQL na stdout zamiast zwracać go jako ciąg, a nie mogę rozpracować sql_deletekodu ...


Fajnie USE DATABASE, polecam ci utworzenie pakietu django -rereate-db z poleceniem zarządzania, które będzie się automatycznie przełączać na podstawie ustawień przełączania między SQLite3 i PostGresql.
Natim

4

Oto skrypt powłoki, który ostatecznie stworzyłem, aby rozwiązać ten problem. Mam nadzieję, że to komuś zaoszczędzi trochę czasu.

#!/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

Używając Pythona do wykonania polecenia flushproject, używasz:

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']])

Moje pytanie, jak to zrobić, jeśli baza danych jeszcze nie istnieje?
Natim

Niestety wszelkie dalsze działania w tym samym skrypcie (np. Syncdb) skutkują błędem „Nie wybrano bazy danych”.
Timmmm

Wykonał polecenie flushdbi po uruchomieniu innego polecenia. jeśli potrzebujesz tego w innym skrypcie, możesz użyćcall_command
Natim

Nie nadążam. Już używam call_command. Mówisz, że powinienem zrobić call_command("flushdb")wcześniej call_command("syncdb")?
Timmmm

Nie działa. Ten sam błąd. Błąd to „Nie wybrano bazy danych”, więc nie można wykonać żadnego kodu SQL. Znalazłem rozwiązanie: zobacz moją drugą odpowiedź.
Timmmm

1

Polecenie ./manage.py sqlclearlub ./manage.py sqlflushwydaje się, aby wyczyścić stół, a nie je usunąć, jednak jeśli chcesz usunąć pełna baza spróbuj tego: manage.py flush.

Ostrzeżenie: spowoduje to całkowite usunięcie bazy danych i utratę wszystkich danych, więc jeśli nie jest to ważne, spróbuj.


2
Nie, to nieprawda. flush i sqlflush to to samo, usuwa wszystkie dane, ale nie usuwa tabel. sqlflush wyświetla sql, ale nie wykonuje, flush wykonuje go bez wyświetlania.
Moulde,

1

Oto przykład Makefile do robienia fajnych rzeczy z wieloma plikami ustawień:

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

Następnie możesz wykonać następujące czynności: $ make db_reset


1

Ta odpowiedź dotyczy postgresql DB:

Run: echo 'drop należący do some_user ' | ./manage.py dbshell

UWAGA: some_user to nazwa użytkownika, którego używasz do uzyskiwania dostępu do bazy danych, zobacz plik settings.py:

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

1

Jeśli używasz psql i masz zainstalowane django-more 2.0.0, możesz to zrobić

manage.py reset_schema


0

Oto wersja odpowiedzi @ peter-g poświęcona migracji na południe. Często bawię się w surowym sql, więc przydaje się to jako 0001_initial.py dla wszelkich zdezorientowanych aplikacji. Będzie działać tylko na bazach danych, które obsługują SHOW TABLES(jak mysql). Zastąp coś takiego SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';, jak jeśli używasz PostgreSQL. Często robię to samo w przypadku migracji forwardsi backwardsmigracji.

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

Jednak współpracownicy / współkoderzy zabiliby mnie, gdyby wiedzieli, że to zrobiłem.


0

Jest jeszcze prostsza odpowiedź, jeśli chcesz usunąć WSZYSTKIE swoje stoły. Po prostu przejdź do folderu zawierającego bazę danych (który może mieć nazwę mydatabase.db), kliknij prawym przyciskiem myszy plik .db i naciśnij „usuń”. Staromodny sposób, z pewnością zadziała.


1
Jednak tylko dla baz danych sqlite :-)
winwaed

0

Upuszcza wszystkie tabele i odtwarza je:

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

Wyjaśnienie:

manage.py sqlclear - "wyświetla instrukcje SQL DROP TABLE dla podanych nazw aplikacji"

sed -n "2,$p" - przechwytuje wszystkie linie z wyjątkiem pierwszej linii

sed -n "$ !p" - przechwytuje wszystkie linie oprócz ostatniej linii

sed "s/";/" CASCADE;/" - zastępuje wszystkie średniki (;) przez (CASCADE;)

sed -e "1s/^/BEGIN;/" -e "$s/$/COMMIT;/" - wstawia (BEGIN;) jako pierwszy tekst, wstawia (COMMIT;) jako ostatni tekst

manage.py dbshell - „Uruchamia klienta wiersza poleceń dla silnika bazy danych określonego w ustawieniach ENGINE, z parametrami połączenia określonymi w ustawieniach USER, PASSWORD itp.”

manage.py syncdb - "Tworzy tabele bazy danych dla wszystkich aplikacji w INSTALLED_APPS, których tabele nie zostały jeszcze utworzone"

Zależności:


Kredyty:

@Manoj Govindan i @Mike DeSimone dla sqlclear przesłano do dbshell

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



Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.