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?

Kmalmur
fonte

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

Manoj Govindan
fonte
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).

Anuj Gupta
fonte
@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.

Mike DeSimone
fonte
+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?

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fonte
12

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

FeroxTL
fonte
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)
lemanyk
fonte
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 ...

Timmmm
fonte
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
Peter G
fonte
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']])
Natim
fonte
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.

iyogeshjoshi
fonte
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

daino3
fonte
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': '',
}
Kostyantyn
fonte
1

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

manage.py reset_schema

Alice Purcell
fonte
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.

fogões
fonte
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.

Rock Lee
fonte
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; /"'

Stephen Cernota
fonte
0

use o comando "python manage.py sqlflush" no Windows 10 para outros, digite manage.py

Tannu Yadav
fonte
o que você quer dizer??
tannu yadav de
0

Eu recomendo que você instale extensões django e usepython manage.py reset_db comando. Ele faz exatamente o que você deseja.

Diego aragão
fonte