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

Posted

技术标签:

【中文标题】如何使用 Django 中的 manage.py CLI 从数据库中删除所有表?【英文标题】:How to drop all tables from the database with manage.py CLI in Django? 【发布时间】:2011-03-25 18:17:48 【问题描述】:

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

【问题讨论】:

【参考方案1】:

手动删除数据库迁移的解决方案。

manage.py同级,创建clean.py

import os


def recursor(dirpath):
    # print(dirpath)
    delfiles = []
    deldirs = []
    with os.scandir(dirpath) as l1:
        for e1 in l1:
            if not e1.is_file():
                with os.scandir(e1.path) as l2:
                    for e2 in l2:
                        if e2.name == 'migrations':
                            with os.scandir(e2.path) as l3:
                                for e3 in l3:
                                    if not e3.name == '__init__.py':
                                        print(e3.path)
                                        if e3.is_file():
                                            delfiles.append(e3.path)
                                        else:
                                            deldirs.append(e3.path)
                                            with os.scandir(e3.path) as l4:
                                                for e4 in l4:
                                                    delfiles.append(e4)
    yn = input('are you sure to delete all the files above?(y/n)')
    if yn == 'y':
        for dp in delfiles:
            os.remove(dp)
        for dp in deldirs:
            os.rmdir(dp)



recursor(os.path.dirname(os.path.realpath(__file__)))

删除db.sqlite3文件并运行clean.py

【讨论】:

【参考方案2】:

我建议你安装django-extensions 并使用python manage.py reset_db 命令。它完全符合您的要求。

【讨论】:

【参考方案3】:

如果你使用 psql 并安装了 django-more 2.0.0,你可以这样做

manage.py reset_schema

【讨论】:

【参考方案4】:

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

更新: 无耻盗用@Mike DeSimone在本答案下方的评论,给出完整答案。

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

从 django 1.9 开始,它现在是 ./manage.py sqlflush

【讨论】:

sqlclear "打印 drop 语句" 但如何在单个命令行调用中执行它们 您需要的应​​用名称如:./manage.py sqlclear myAppName | ./manage.py dbshell 这根本不起作用。 sqlclear 需要一个应用名称。我在 Django 1.8 请注意 sqlflush 不会删除表,它会截断它们。此外,除非您在 sqlflush 生成的 truncate 命令末尾添加 CASCADE 关键字,否则此操作可能不适用于您的 postgresql DB。 不是./manage.py sqlclear,对我来说是sqlflush【参考方案5】:

此答案适用于 postgresql DB:

运行: 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': '',

【讨论】:

【参考方案6】:

在 Windows 10 中使用“python manage.py sqlflush”命令 对于其他人,请键入 manage.py

【讨论】:

你想说什么??【参考方案7】:

这是一个使用多个设置文件做一些好事的 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

【讨论】:

【参考方案8】:

python manage.py migrate <app> zero

sqlclear 已从 1.9 中删除。

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

很遗憾,我找不到同时适用于所有应用的方法,也找不到从管理员那里列出所有已安装应用的内置方法:How to list all installed apps with manage.py in Django?

相关:How to reset migrations in Django 1.7?

【讨论】:

sqlflush 怎么样?【参考方案9】:

命令./manage.py sqlclear./manage.py sqlflush 似乎是清除表而不是删除它们,但是如果你想删除整个数据库,试试这个:manage.py flush

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

【讨论】:

不,这是不正确的。 flush 和 sqlflush 是一样的,它会删除所有数据,但不会删除表。 sqlflush 显示sql,但不执行,flush 执行不显示。【参考方案10】:

最好使用./manage.py sqlflush | ./manage.py dbshell,因为sqlclear需要应用刷新。

【讨论】:

【参考方案11】:

如果您想完全擦除数据库并在同一时间重新同步它,您需要类似以下内容。我还在此命令中结合添加测试数据:

#!/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-recreate-db 包,该命令将根据设置自动切换以在 SQLite3 和 PostGresql 之间切换。【参考方案12】:

没有用于删除所有表的原生 Django 管理命令。 sqlclearreset 都需要应用名称。

但是,您可以安装Django Extensions,它会为您提供manage.py reset_db,它完全可以满足您的需求(并让您可以访问many more 有用的管理命令)。

【讨论】:

@JulienGreard 已更新。谢谢! 我放弃尝试并使用了这个。 这对我有用,而排名较高的答案都没有。 @AnujGupta 也经常 manage.py reset_db 需要标志 `-c, --close-sessions` 在删除数据库之前关闭数据库连接(仅限 PostgreSQL) 它给了我用户'MYUSERNAME'@'localhost'的访问被拒绝(使用密码:否)【参考方案13】:

删除所有表并重新创建它们:

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 中尚未创建表的所有应用创建数据库表"

依赖关系:

sed,为了在 Windows 上使用,我安装了 UnxUtils: (Download) (Installation Instructions)

致谢:

@Manoj Govindan 和 @Mike DeSimone 用于 sqlclear 管道传输到 dbshel​​l

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

【讨论】:

【参考方案14】:

如果您想删除所有表格,还有一个更简单的答案。您只需转到包含数据库的文件夹(可能称为 mydatabase.db)并右键单击 .db 文件并按“删除”。老式的方式,肯定能工作。

【讨论】:

仅适用于 sqlite 数据库 :-)【参考方案15】:

这是@peter-g 答案的南迁版本。 我经常摆弄原始 sql,因此对于任何迷惑的应用程序,它都可以作为 0001_initial.py 派上用场。它只适用于支持SHOW TABLES(如mysql)的数据库。如果您使用 PostgreSQL,请替换 SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'; 之类的内容。另外,我经常对 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()))

不过,如果同事/编码员知道我这样做,他们会杀了我。

【讨论】:

【参考方案16】:

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

【讨论】:

【参考方案17】:

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

【讨论】:

我的问题是,如果数据库尚不存在,如何执行此操作? 遗憾的是,同一脚本中的任何进一步操作(例如 syncdb)都会导致“未选择数据库”错误。 它执行了一个命令flushdb,在我启动另一个命令之后。如果你在另一个脚本中需要它,你可以使用call_command 我不关注。我已经在使用call_command。你是说我应该在call_command("syncdb") 之前做call_command("flushdb") 不起作用。同样的错误。错误是“未选择数据库”,因此您无法执行 any SQL。找到解决方案:查看我的其他答案。【参考方案18】:

这是我最后拼凑起来的一个 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

【讨论】:

【参考方案19】:

如果您使用 South 包来处理数据库迁移(强烈推荐),那么您可以使用 ./manage.py migrate appname zero 命令。

否则,我会推荐 ./manage.py dbshell 命令,在标准输入上的 SQL 命令中管道。

【讨论】:

+1。任何重要的 Django 项目都应该使用 South。一旦你使用 South,那么迁移到零是删除所有表的一种很好的惯用方式。 即使是微不足道的 Django 项目也应该考虑 South。只是为了让人们习惯迁移数据库,这样他们就不会养成诸如尝试手动转储、破解和重新加载数据或使用固定装置机制迁移数据的坏习惯。 我确实使用 South,但我不会为每次迁移都编写反向迁移:尤其是数据迁移。而且我不会这样做,只是为了可以使用零选项。如果这对您很重要,那当然是一种很好的测试方法,您 / 可以 / 将其反转回零。删除所有表格对我来说似乎是合理的。 当然......如果你有大量的“应用程序”怎么办 嗯,这个问题很古老,South 在 1.7 左右被纳入 Django,我使用命令将数十个应用程序迁移到零。 reset_db(上图)是我首选的用于消除所有内容的工具,但我也使用 migrate 来回到零。 Django 非常擅长在创建迁移时捕获跨应用程序依赖项,因此将 auth 之类的内容滚动回零几乎可以获得所有内容。

以上是关于如何使用 Django 中的 manage.py CLI 从数据库中删除所有表?的主要内容,如果未能解决你的问题,请参考以下文章

如何仅使用 django manage.py makemessages 创建 .pot 文件

如何直接从测试驱动程序调用自定义 Django manage.py 命令?

如何查看在 Django 的 manage.py test 命令期间运行了哪些测试

初试django---python manage.py makemigrations以及python manage.py migrate

使用 manage.py shell 更改 Django 站点显示名称?

Heroku 上的 Django manage.py 自定义命令