Como eliminar todas as tabelas do banco de dados com manage.py CLI no Django?


92

Como posso eliminar todas as tabelas de um banco de dados usando manage.py e linha de comando? Existe alguma maneira de fazer isso executando manage.py com parâmetros apropriados para que eu possa executá-lo a partir de um aplicativo .NET?

Respostas:


127

Pelo que eu sei, não existe um comando de gerenciamento para eliminar todas as tabelas. Se você não se importa em hackear Python, pode escrever seu próprio comando personalizado para fazer isso. Você pode achar a sqlclearopção interessante. A documentação diz que ./manage.py sqlclear imprime as instruções DROP TABLE SQL para os nomes de aplicativos fornecidos.

Atualização : Desavergonhadamente apropriando-se do comentário de @Mike DeSimone abaixo desta resposta para dar uma resposta completa.

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

No Django 1.9 agora é ./manage.py sqlflush


sqlclear "imprime as instruções drop", mas como executá-las em uma única chamada de linha de comando
kmalmur

3
você precisa do nome do aplicativo como:./manage.py sqlclear myAppName | ./manage.py dbshell
Montaro

4
Isso não funciona de jeito nenhum. sqlclear precisa de um nome de aplicativo. Estou no Django 1.8
Jonathan Hartley

Esteja ciente de que o sqlflush não remove as tabelas, ele as trunca. Além disso, essa operação provavelmente não funcionará em seu banco de dados postgresql a menos que você adicione a palavra-chave CASCADE no final do comando truncate gerado por sqlflush.
user3748764 de

35

Não há comando de gerenciamento Django nativo para eliminar todas as tabelas. Ambos sqlcleare resetexigem um nome de aplicativo.

No entanto, você pode instalar extensões Django que fornecem a você manage.py reset_db, o que faz exatamente o que você deseja (e fornece acesso a muitos outros comandos de gerenciamento úteis).


@JulienGreard atualizado. Obrigado!
Anuj Gupta

3
Desisti de tentar e usei isso.
laffuste

Isso funcionou para mim, enquanto nenhuma das respostas com classificação mais alta funcionou.
Jonathan Hartley

@AnujGupta também frequentemente manage.py reset_dbprecisa do sinalizador `-c, --close-sessions` para fechar as conexões do banco de dados antes de descartar o banco de dados (somente PostgreSQL)
Valery Ramusik

34

Se você estiver usando o pacote South para lidar com migrações de banco de dados (altamente recomendado), você pode apenas usar o ./manage.py migrate appname zerocomando.

Caso contrário, eu recomendaria o ./manage.py dbshellcomando, canalizando comandos SQL na entrada padrão.


+1. Qualquer projeto Django não trivial deve usar South. E depois de usar o Sul, migrar para o Zero é uma maneira idiomática legal de eliminar todas as tabelas.
Manoj Govindan

Mesmo projetos triviais de Django devem considerar o sul. Apenas para acostumar as pessoas a migrar bancos de dados e não aprender maus hábitos, como tentar despejar, hackear e recarregar dados manualmente ou usar o mecanismo de acessórios para migrar dados.
Mike DeSimone

Eu uso o South, mas não me preocupo em escrever migrações reversas para cada migração: principalmente migrações de dados. E eu não faria isso apenas para usar a opção zero. Certamente uma boa maneira de testar que você / pode / reverter de volta a zero, se isso for importante para você. Deixar cair todas as mesas parece-me razoável.
tobych

26

python manage.py migrate <app> zero

sqlclear foi removido do 1.9.

As notas de lançamento mencionam que é devido à introdução de migrações: https://docs.djangoproject.com/en/1.9/releases/1.9/

Infelizmente, não consegui encontrar um método que funcione em todos os aplicativos ao mesmo tempo, nem uma maneira integrada de listar todos os aplicativos instalados pelo administrador: Como listar todos os aplicativos instalados com manage.py no Django?

Relacionado: Como redefinir migrações no Django 1.7?


12

É melhor usar ./manage.py sqlflush | ./manage.py dbshellporque sqlclear requer aplicativo para liberar.


7

maneira simples (?) de fazer isso em python (no 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

Se você deseja limpar completamente o banco de dados e sincronizá-lo novamente, você precisa de algo como o seguinte. Eu também combino a adição de dados de teste neste comando:

#!/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() # ...

Seria bom poder fazer, cursor.execute(call_command('sqlclear', 'main'))mas call_commandimprimir o SQL em stdout em vez de retorná-lo como uma string, e eu não consigo descobrir o sql_deletecódigo ...


Agradável USE DATABASE, recomendo que você crie um pacote django-recreate-db com um comando de gerenciamento que irá alternar automaticamente com base nas configurações para alternar entre SQLite3 e PostGresql.
Natim

4

Aqui está um script de shell que acabei montando para lidar com esse problema. Espero que economize algum tempo.

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

Usando Python para fazer um comando flushproject, você usa:

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

Minha dúvida, como fazer isso se o banco de dados ainda não existe?
Natim

Infelizmente, quaisquer outras ações no mesmo script (por exemplo, syncdb) resultam em erros "Nenhum banco de dados selecionado".
Timmmm,

Ele fez um comando flushdbe depois lancei outro comando. se precisar em outro script, você pode usarcall_command
Natim 09/10/12

Eu não sigo. Eu já estou usando call_command. Você está dizendo que eu deveria fazer call_command("flushdb")antes call_command("syncdb")?
Timmmm,

Não funciona. Mesmo erro. O erro é "Nenhum banco de dados selecionado", portanto, você não pode executar nenhum SQL. Encontrei a solução: veja minha outra resposta.
Timmmm de

1

O comando ./manage.py sqlclearou ./manage.py sqlflushparece limpar a mesa e não excluí-los, no entanto, se você deseja excluir o banco de dados completo tente o seguinte: manage.py flush.

Aviso: isso excluirá seu banco de dados completamente e você perderá todos os seus dados, então se isso não for importante, vá em frente e experimente.


2
Não, isso está incorreto. flush e sqlflush são iguais, ele remove todos os dados, mas não remove as tabelas. sqlflush exibe o sql, mas não executa, flush o executa sem exibi-lo.
Moulde

1

Aqui está um Makefile de exemplo para fazer algumas coisas boas com vários arquivos de configurações:

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

Então você pode fazer coisas como: $ make db_reset


1

Esta resposta é para o banco de dados postgresql:

Executar: echo 'drop propriedade de some_user ' | ./manage.py dbshell

NOTA: some_user é o nome do usuário que você usa para acessar o banco de dados, consulte o arquivo settings.py:

default_database = {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'somedbname',
    'USER': 'some_user',
    'PASSWORD': 'somepass',
    'HOST': 'postgresql',
    'PORT': '',
}

1

Se você estiver usando psql e tiver django-more 2.0.0 instalado, você pode fazer

manage.py reset_schema


0

Aqui está uma versão de migração para o sul da resposta de @peter-g. Costumo brincar com sql bruto, então isso é útil como 0001_initial.py para qualquer aplicativo confuso. Ele só funcionará em bancos de dados que suportam SHOW TABLES(como o mysql). Substitua por algo como SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';se você usar PostgreSQL. Além disso, geralmente faço exatamente a mesma coisa para as migrações forwardse 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()))

No entanto, colegas de trabalho / cocodificadores me matariam se soubessem que fiz isso.


0

Há uma resposta ainda mais simples se você quiser excluir TODAS as suas tabelas. Basta ir para a pasta que contém o banco de dados (que pode ser chamado de mydatabase.db), clicar com o botão direito do mouse no arquivo .db e pressionar "excluir". Maneira antiquada, infalível de trabalhar.


1
Porém, apenas para bancos de dados sqlite :-)
winwaed

0

Descarta todas as tabelas e as recria:

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

Explicação:

manage.py sqlclear - "imprime as instruções SQL DROP TABLE para os nomes de aplicativos fornecidos"

sed -n "2,$p" - pega todas as linhas, exceto a primeira linha

sed -n "$ !p" - pega todas as linhas, exceto a última linha

sed "s/";/" CASCADE;/" - substitui todos os pontos-e-vírgulas (;) por (CASCADE;)

sed -e "1s/^/BEGIN;/" -e "$s/$/COMMIT;/" - insere (BEGIN;) como primeiro texto, insere (COMMIT;) como último texto

manage.py dbshell - "Executa o cliente de linha de comando para o mecanismo de banco de dados especificado em sua configuração ENGINE, com os parâmetros de conexão especificados em sua configuração USER, PASSWORD, etc."

manage.py syncdb - "Cria as tabelas de banco de dados para todos os aplicativos em INSTALLED_APPS cujas tabelas ainda não foram criadas"

Dependências:


Créditos:

@Manoj Govindan e @Mike DeSimone para sqlclear canalizado para dbshell

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



Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.