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

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

【问题讨论】:

    标签: mysql django django-admin


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

                依赖关系:


                致谢:

                @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 之类的内容滚动回零几乎可以获得所有内容。
                        猜你喜欢
                        • 2011-05-30
                        • 2020-04-18
                        • 1970-01-01
                        • 2011-06-06
                        • 2011-09-23
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多