如何使用 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 dbshell
注意: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 管理命令。 sqlclear
和 reset
都需要应用名称。
但是,您可以安装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 管道传输到 dbshell
@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';
之类的内容。另外,我经常对 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()))
不过,如果同事/编码员知道我这样做,他们会杀了我。
【讨论】:
【参考方案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