Как удалить все таблицы из базы данных с помощью интерфейса командной строки manage.py в Django?


95

Как удалить все таблицы из базы данных с помощью manage.py и командной строки? Есть ли способ сделать это, выполнив manage.py с соответствующими параметрами, чтобы я мог выполнить его из приложения .NET?

Ответы:


128

Насколько я знаю, нет команды управления для удаления всех таблиц. Если вы не против взлома Python, вы можете написать для этого свою собственную команду. Возможно, вам понравится этот sqlclearвариант. В документации говорится, что ./manage.py sqlclear выводит операторы SQL DROP TABLE для заданных имен приложений.

Обновление : бесстыдное присвоение комментария @Mike DeSimone под этим ответом, чтобы дать полный ответ.

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

Начиная с django 1.9 это сейчас ./manage.py sqlflush


sqlclear «печатает операторы перетаскивания», но как их выполнить в одном вызове командной строки
— kmalmur

3
вам нужно название приложения, например:./manage.py sqlclear myAppName | ./manage.py dbshell
— Montaro

4
Это вообще не работает. sqlclear требуется имя приложения. Я использую Django 1.8
— Джонатан Хартли

1
Просто имейте в виду, что sqlflush не удаляет таблицы, а обрезает их. Также эта операция, вероятно, не будет работать в вашей базе данных postgresql, если вы не добавите ключевое слово CASCADE в конце команды усечения, созданной sqlflush.
— user3748764

39

Нет встроенной команды управления Django для удаления всех таблиц. Оба sqlclearи resetтребуют имени приложения.

Однако вы можете установить Django Extensions, который дает вам то manage.py reset_db, что делает именно то, что вы хотите (и дает вам доступ ко многим другим полезным командам управления).


@JulienGreard Обновлено. Благодарность!
— Anuj Gupta

4
Я бросил попытки и использовал это.
— laffuste

Это сработало для меня, в то время как ни один из ответов с более высоким рейтингом не помог.
— Джонатан Хартли,

1
@AnujGupta также часто manage.py reset_dbтребуется флаг `-c, --close-sessions` для закрытия соединений с базой данных перед удалением базы данных (только для PostgreSQL)
— Валерий Рамусик

34

Если вы используете пакет South для обработки миграции базы данных (настоятельно рекомендуется), вы можете просто использовать ./manage.py migrate appname zeroкоманду.

В противном случае я бы порекомендовал ./manage.py dbshellкоманду, вводящую команды SQL в стандартный ввод.


+1. Любой нетривиальный проект Django должен использовать South. И как только вы используете Юг, переход на Zero - хороший идиоматический способ отбросить все таблицы.
— Манодж Говиндан

Даже тривиальные проекты Django должны учитывать Юг. Просто чтобы люди привыкли к миграции баз данных, и чтобы они не усвоили плохие привычки, такие как попытки сбросить, взломать и перезагрузить данные вручную или использовать механизм фикстур для миграции данных.
— Майк Дезимоун

Я использую Юг, но я не утруждаюсь писать обратные миграции для каждой миграции: не в последнюю очередь миграции данных. И я бы не стал этого делать только для того, чтобы использовать нулевой вариант. Безусловно, хороший способ тестирования, который вы / можете / вернуть обратно к нулю, если это важно для вас. Отказ от всех таблиц кажется мне разумным.
— тобыч

26

python manage.py migrate <app> zero

sqlclear был удален из 1.9.

В примечаниях к выпуску упоминается, что это связано с введением миграций: https://docs.djangoproject.com/en/1.9/releases/1.9/

К сожалению, я не смог найти ни метода, который работал бы со всеми приложениями одновременно, ни встроенного способа перечислить все установленные приложения от администратора: как вывести список всех установленных приложений с помощью manage.py в Django?

Связанный: Как сбросить миграции в Django 1.7?


12

Лучше использовать, ./manage.py sqlflush | ./manage.py dbshellпотому что sqlclear требует, чтобы приложение было сброшено.


7

простой (?) способ сделать это из python (на 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

Если вы хотите полностью стереть базу данных и повторно синхронизировать ее одновременно, вам понадобится что-то вроде следующего. Я также комбинирую добавление тестовых данных в эту команду:

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

Было бы хорошо , чтобы быть в состоянии сделать , cursor.execute(call_command('sqlclear', 'main'))но call_commandпечатает SQL на стандартный вывод , а не возвращать его в виде строки, и я не могу работать в sql_deleteкод ...


Приятно, что USE DATABASEя рекомендую вам создать пакет django-reconate-db с командой управления, которая будет автоматически переключаться в зависимости от настроек для переключения между SQLite3 и PostGresql.
— Натим

4

Вот сценарий оболочки, который я собрал по кусочкам для решения этой проблемы. Надеюсь, это кому-то сэкономит время.

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

Используя Python для создания команды flushproject, вы используете:

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

К сожалению, любые дальнейшие действия в том же сценарии (например, syncdb) приводят к ошибкам «База данных не выбрана».
— Timmmm 08

Он выполнил команду, flushdbи после того, как я запустил другую команду. если вам это нужно в другом сценарии, вы можете использоватьcall_command
— Натим

Я не слежу. Уже пользуюсь call_command. Вы говорите, что я должен сделать call_command("flushdb")раньше call_command("syncdb")?
— Timmmm

Не работает. Та же ошибка. Ошибка: «База данных не выбрана», поэтому вы не можете выполнить какой-либо SQL. Нашел решение: см. Мой другой ответ.
— Timmmm

1

Команда ./manage.py sqlclearили, ./manage.py sqlflushкажется, очищает таблицу, а не удаляет их, однако, если вы хотите удалить всю базу данных, попробуйте следующее:manage.py flush .

Предупреждение: это полностью удалит вашу базу данных, и вы потеряете все свои данные, поэтому, если это не важно, попробуйте.


2
Нет, это неверно. flush и sqlflush одинаковы, он удаляет все данные, но не удаляет таблицы. sqlflush отображает sql, но не выполняет, flush выполняет его без отображения.
— Moulde 08

1

Вот пример Makefile, чтобы делать приятные вещи с несколькими файлами настроек:

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

Затем вы можете делать такие вещи, как: $ make db_reset


1

Этот ответ предназначен для БД postgresql:

Выполнить: echo 'drop, владельцем которого является some_user ' | ./manage.py dbshell

ПРИМЕЧАНИЕ: some_user - это имя пользователя, которого вы используете для доступа к базе данных, см. Файл settings.py:

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


0

Вот версия ответа @peter-g на юг. Я часто играю с необработанным sql, поэтому он пригодится как 0001_initial.py для любых сбитых с толку приложений. Он будет работать только с БД, которые поддерживают SHOW TABLES(например, mysql). Замените что-то вроде, SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';если вы используете PostgreSQL. Кроме того, я часто делаю одно и то же как для миграции, так forwardsи для 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()))

Однако коллеги / сокодеры убили бы меня, если бы узнали, что я это сделал.


0

Есть еще более простой ответ, если вы хотите удалить ВСЕ свои таблицы. Вам просто нужно перейти в свою папку, содержащую базу данных (которая может называться mydatabase.db), щелкнуть правой кнопкой мыши файл .db и нажать «удалить». Старомодный способ, надежный для работы.


1
Только для баз данных sqlite :-)
— winwaed

0

Удаляет все таблицы и воссоздает их:

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

Пояснение:

manage.py sqlclear - «печатает операторы SQL DROP TABLE для заданных имен приложений»

sed -n "2,$p" - захватывает все строки, кроме первой

sed -n "$ !p" - захватывает все строки, кроме последней

sed "s/";/" CASCADE;/" - заменяет все точки с запятой (;) на (CASCADE;)

sed -e "1s/^/BEGIN;/" -e "$s/$/COMMIT;/" - вставляет (BEGIN;) как первый текст, вставляет (COMMIT;) как последний текст

manage.py dbshell - "Запускает клиент командной строки для ядра базы данных, указанного в настройках ENGINE, с параметрами подключения, указанными в настройках ПОЛЬЗОВАТЕЛЯ, ПАРОЛЯ и т. Д."

manage.py syncdb - «Создает таблицы базы данных для всех приложений в INSTALLED_APPS, таблицы которых еще не были созданы»

Зависимости:


Кредиты:

@Manoj Govindan и @Mike DeSimone для sqlclear подключены к dbshell

@jpic для 'sed "s /"; / "CASCADE; /"'



Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.