如何在Django中使用manage.py CLI从数据库中删除所有表?


92

如何使用manage.py和命令行从数据库中删除所有表?有什么方法可以执行带有适当参数的manage.py,以便可以从.NET应用程序执行它?

Answers:


127

据我所知,没有任何管理命令可以删除所有表。如果您不介意黑客Python,则可以编写自己的自定义命令来实现。您可能会发现该sqlclear选项很有趣。文档说,./manage.py sqlclear 为给定的应用程序名称打印DROP TABLE SQL语句。

更新:在此答案下方无耻地占用@Mike DeSimone的评论以提供完整的答案。

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

从Django 1.9开始 ./manage.py sqlflush


sqlclear“打印drop语句”,但如何在单个命令行调用中执行它们
kmalmur 2010年

3
您需要使用以下应用名称:./manage.py sqlclear myAppName | ./manage.py dbshell
Montaro 2015年

4
这根本不起作用。sqlclear需要一个应用程序名称。我使用的是Django 1.8
Jonathan Hartley

请注意,sqlflush不会删除表,而是会截断它们。另外,除非在sqlflush生成的truncate命令的末尾添加CASCADE关键字,否则此操作可能不适用于您的Postgresql DB。
user3748764

35

没有本地Django管理命令可删除所有表。无论sqlclearreset需要的应用程序名称。

但是,您可以安装Django的扩展,让你manage.py reset_db,这不正是你想要什么(让你获得更多的有用的管理命令)。


@JulienGreard更新。谢谢!
Anuj Gupta 2014年

3
我放弃尝试并使用了它。
laffuste 2014年

这对我有用,而排名较高的答案都没有。
乔纳森·哈特利

@AnujGupta通常还 manage.py reset_db需要标记`-c,--close-sessions`才能在删除数据库之前关闭数据库连接(仅适用于PostgreSQL)
Valery Ramusik

34

如果您正在使用South包来处理数据库迁移(强烈建议),则可以只使用./manage.py migrate appname zero命令。

否则,我建议./manage.py dbshell使用标准输入中的SQL命令中的命令。


+1。任何重要的Django项目都应使用South。一旦使用South,然后迁移到零是删除所有表的一种惯用方式。
Manoj Govindan

即使是琐碎的Django项目也应该考虑南方。仅仅是为了使人们习惯于迁移数据库,因此他们不会学习不良习惯,例如尝试手动转储,修改和重新加载数据,或者使用固定装置机制迁移数据。
Mike DeSimone

我确实使用过South,但是我不会为每个迁移编写反向迁移:尤其是数据迁移。而且我不会那样做,所以我可以使用零选项。如果这对您很重要,那么肯定是一种测试您可以/可以/回到零的好方法。丢掉所有桌子对我来说似乎很合理。
tobych 2014年

26

python manage.py migrate <app> zero

sqlclear 从1.9中删除。

发行说明提到这是​​由于引入了迁移:https : //docs.djangoproject.com/en/1.9/releases/1.9/

不幸的是,我找不到一次可在所有应用程序上运行的方法,也找不到从管理员列出所有已安装应用程序的内置方法:如何在Django中列出带有manage.py的所有已安装应用程序?

相关:如何在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 2012年

4

这是我最终拼凑起来的Shell脚本,以解决此问题。希望它可以节省一些时间。

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

遗憾的是,同一脚本(例如,syncdb)中的任何其他操作都将导致“未选择数据库”错误。
Timmmm

它执行了一个命令flushdb,然后启动了另一个命令。如果您需要其他脚本中的内容,则可以使用call_command
Natim 2012年

我不懂 我已经在使用了call_command。你说我应该怎么做call_command("flushdb")之前call_command("syncdb")
Timmmm 2012年

不起作用 同样的错误。错误是“未选择数据库”,因此您无法执行任何 SQL。找到了解决方案:请参阅我的其他答案。
Timmmm 2012年

1

该命令./manage.py sqlclear./manage.py sqlflush似乎清除了表并没有删除它们,但是,如果要删除整个数据库,请尝试以下操作:manage.py flush

警告: 这将完全删除您的数据库,并且您将丢失所有数据,因此如果不重要,请继续尝试。


2
不,这是不正确的。flush和sqlflush相同,它删除所有数据,但不删除表。sqlflush显示sql,但不执行,flush在不显示的情况下执行它。
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 dbshel​​l

注意: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,请替换类似的内容。另外,对于forwardsbackwards迁移,我经常做同样的事情。

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数据库:-)
13年

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 -“使用在USER,PASSWORD等设置中指定的连接参数,为ENGINE设置中指定的数据库引擎运行命令行客户端”

manage.py syncdb -“为尚未创建表的INSTALLED_APPS中的所有应用程序创建数据库表”

依存关系:


学分:

@Manoj Govindan和@Mike DeSimone用于将sqlclear传递到dbshel​​l

@jpic代表“ sed“ s /”; /“级联; /”'



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.