Як скинути всі таблиці з бази даних за допомогою CLI manage.py в Django?


92

Як я можу скинути всі таблиці з бази даних за допомогою manage.py та командного рядка? Чи є спосіб зробити це, виконуючи manage.py з відповідними параметрами, щоб я міг виконати його з програми .NET?

Відповіді:


127

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

Оновлення : Безсоромно привласнюючи коментар @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

35

Немає власної команди управління Django, щоб скинути всі таблиці. І те, sqlclearі resetінше вимагає імені програми.

Тим не менш, ви можете встановити розширення Django, яке надає вам manage.py reset_db, що робить саме те, що ви хочете (і дає вам доступ до багатьох інших корисних команд управління).


@JulienGreard Оновлено. Дякую!
Анудж Гупта

3
Я відмовився від спроб і використав це.
laffuste

Це спрацювало для мене, тоді як жодна з вищих відповідей не працювала.
Джонатан Хартлі,

@AnujGupta також часто manage.py reset_dbпотребує прапорця `-c, --close-session`, щоб закрити з'єднання з базою даних перед тим, як скинути базу даних (лише для PostgreSQL)
Валерій Рамусік,

34

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

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


+1. Будь-який нетривіальний проект Django повинен використовувати південь. І як тільки ви використовуєте Південь, тоді перехід на Нуль - це чудовий ідіоматичний спосіб скинути всі таблиці.
Manoj Govindan

Навіть тривіальні проекти Джанго повинні враховувати Південь. Просто для того, щоб привчити людей мігрувати бази даних, і щоб вони не навчилися шкідливим звичкам, таким як спроби збору, злому та перезавантаження даних вручну, або використання механізму приладів для міграції даних.
Mike DeSimone

Я справді використовую південь, але я не заважаю писати зворотні міграції для кожної міграції: не в останню чергу міграції даних. І я б не робив цього лише для того, щоб я міг використовувати нульовий варіант. Безумовно, хороший спосіб перевірити, що ви / можете / повернути назад до нуля, якщо це для вас важливо. Кинути всі таблиці мені здається розумним.
тобич

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 в stdout, а не повертає його як рядок, і я не можу опрацювати sql_deleteкод ...


Приємно, USE DATABASEя рекомендую вам створити пакет django-recreate-db з командою управління, яка автоматично переключатиметься на основі налаштувань для перемикання між SQLite3 та PostGresql.
Natim

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

Він зробив команду, flushdbі після того, як я запустив іншу команду. якщо вам це потрібно в іншому сценарії, ви можете використовуватиcall_command
Natim,

Я не слідкую. Я вже використовую 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, але не виконує, флеш виконує його, не відображаючи.
Moulde

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': '',
}

1

Якщо ви використовуєте psql і встановили django-more 2.0.0, ви можете це зробити

manage.py reset_schema


0

Ось південна версія міграції відповіді @ peter-g. Я часто возиться з raw 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 :-)
виграно

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 - "друкує оператори DROP TABLE SQL для вказаних імен додатка"

sed -n "2,$p" - захоплює всі рядки, крім першого рядка

sed -n "$ !p" - захоплює всі рядки, крім останнього

sed "s/";/" CASCADE;/" - замінює всі крапки з комою (;) на (CASCADE;)

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

manage.py dbshell - "Запускає клієнт командного рядка для механізму баз даних, зазначеного у вашому налаштуванні ENGINE, із параметрами з'єднання, зазначеними у налаштуваннях USER, PASSWORD тощо"

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.