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:
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 sqlclear
opcja 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
./manage.py sqlclear myAppName | ./manage.py dbshell
Nie ma natywnego polecenia zarządzania Django, które usuwałoby wszystkie tabele. Obie sqlclear
i reset
wymagają nazwy aplikacji.
Możesz jednak zainstalować rozszerzenia Django, które dają ci manage.py reset_db
dokładnie to, co chcesz (i dają dostęp do wielu bardziej przydatnych poleceń zarządzania).
manage.py reset_db
potrzebuje również flagi `-c, --close-session`, aby zamknąć połączenia z bazą danych przed usunięciem bazy danych (tylko PostgreSQL)
Jeśli używasz pakietu South do obsługi migracji bazy danych (wysoce zalecane), możesz po prostu użyć ./manage.py migrate appname zero
polecenia.
W przeciwnym razie poleciłbym ./manage.py dbshell
polecenie, przesyłając polecenia SQL na standardowe wejście.
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?
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)
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_command
drukuje SQL na stdout zamiast zwracać go jako ciąg, a nie mogę rozpracować sql_delete
kodu ...
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.
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
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']])
flushdb
i po uruchomieniu innego polecenia. jeśli potrzebujesz tego w innym skrypcie, możesz użyćcall_command
call_command
. Mówisz, że powinienem zrobić call_command("flushdb")
wcześniej call_command("syncdb")
?
Polecenie ./manage.py sqlclear
lub ./manage.py sqlflush
wydaje 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.
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
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': '',
}
Jeśli używasz psql i masz zainstalowane django-more 2.0.0, możesz to zrobić
manage.py reset_schema
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 forwards
i backwards
migracji.
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.
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.
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; /"'
użyj polecenia „python manage.py sqlflush” w systemie Windows 10, a inne wpisz manage.py
Zalecałbym zainstalowanie rozszerzeń django i użycie python manage.py reset_db
polecenia. Robi dokładnie to, czego chcesz.