Django'da manage.py CLI ile tüm tabloları veritabanından nasıl bırakabilirim?


95

Manage.py ve komut satırını kullanarak bir veritabanından tüm tabloları nasıl bırakabilirim? Manage.py'yi bir .NET uygulamasından yürütebilmek için uygun parametrelerle yürütmenin herhangi bir yolu var mı?

Yanıtlar:


128

Bildiğim kadarıyla tüm tabloları kaldıracak bir yönetim komutu yok. Python'u kırmaktan çekinmiyorsanız, bunu yapmak için kendi özel komutunuzu yazabilirsiniz. Bu sqlclearseçeneği ilginç bulabilirsiniz . Belgeler , verilen uygulama adları için DROP TABLE SQL ifadelerini yazdırdığını söylüyor ./manage.py sqlclear .

Güncelleme : Tam bir cevap vermek için @Mike DeSimone'nin bu cevabın altındaki yorumunu utanmazca kullanıyorum .

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

Django 1.9'dan itibaren artık ./manage.py sqlflush


sqlclear "drop deyimlerini yazdırır" ancak bunların tek komut satırı çağrısında nasıl çalıştırılacağı
kmalmur

3
aşağıdaki gibi uygulama adına ihtiyacınız var:./manage.py sqlclear myAppName | ./manage.py dbshell
Montaro

4
Bu hiç çalışmıyor. sqlclear'ın bir uygulama adına ihtiyacı var. Django 1.8'deyim
Jonathan Hartley

1
Sqlflush'un tabloları düşürmediğini, kısalttığını unutmayın. Ayrıca sqlflush tarafından oluşturulan truncate komutunun sonuna CASCADE anahtar sözcüğü eklemediğiniz sürece bu işlem postgresql DB'nizde muhtemelen çalışmayacaktır.
user3748764

40

Tüm tabloları bırakacak yerel bir Django yönetim komutu yoktur. Her ikisi de sqlclearve resetbir uygulama adı gerektirir.

Ancak, size tam olarak istediğinizi yapan (ve daha birçok yararlı yönetim komutuna erişim sağlayan) Django Extensions'ı kurabilirsiniz .manage.py reset_db


@JulienGreard Güncellendi. Teşekkürler!
Anuj Gupta

4
Denemekten vazgeçtim ve bunu kullandım.
laffuste

Bu benim için işe yaradı, ancak yüksek dereceli cevapların hiçbiri işe yaramadı.
Jonathan Hartley

1
@AnujGupta de sık sık manage.py reset_dbveritabanını bırakarak önce yakın veritabanı bağlantıları bayrağı `-c, --close-sessions` ihtiyacı (PostgreSQL için)
Valery Ramusik

34

Veritabanı geçişlerini işlemek için Güney paketini kullanıyorsanız (şiddetle tavsiye edilir), o zaman sadece ./manage.py migrate appname zerokomutu kullanabilirsiniz .

Aksi takdirde, ./manage.py dbshellstandart girişte SQL komutlarında borulama komutunu öneririm .


+1. Önemsiz olmayan herhangi bir Django projesi Güney'i kullanmalıdır. Ve güneyi bir kez kullandığınızda, Sıfıra geçiş, tüm tabloları kaldırmanın güzel bir deyimsel yoludur.
Manoj Govindan

Önemsiz Django projeleri bile Güney'i düşünmelidir. İnsanları veri tabanlarını taşımaya alıştırmak ve böylece verileri elle atmaya, hacklemeye ve yeniden yüklemeye çalışmak veya verileri taşımak için fikstür mekanizmasını kullanmak gibi kötü alışkanlıkları öğrenmesinler.
Mike DeSimone

Güney'i kullanıyorum, ancak her geçiş için ters geçişler yazmakla uğraşmıyorum: en az veri geçişleri değil. Ve bunu sadece sıfır seçeneğini kullanabilmek için yapmazdım. Kesinlikle, sizin için önemliyse, sıfıra geri dönebileceğiniz / yapabileceğiniz / tersine çevirebileceğiniz iyi bir test yolu. Tüm masaları düşürmek bana mantıklı geliyor.
tobych

26

python manage.py migrate <app> zero

sqlclear 1.9'dan kaldırıldı.

Sürüm notları, bunun geçişlerin başlamasından kaynaklandığını belirtmektedir: https://docs.djangoproject.com/en/1.9/releases/1.9/

Maalesef aynı anda tüm uygulamalarda çalışan bir yöntem veya yöneticiden tüm yüklü uygulamaları listelemenin yerleşik bir yolunu bulamadım: Manage.py ile tüm yüklü uygulamaları Django'da nasıl listeleyebilirim?

İlgili: Django 1.7'de geçişler nasıl sıfırlanır?


12

Kullanması daha iyidir ./manage.py sqlflush | ./manage.py dbshellçünkü sqlclear, uygulamanın temizlenmesini gerektirir.


7

python'dan yapmanın basit (?) yolu (mysql'de):

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

Veritabanını tamamen silmek ve aynı anda yeniden senkronize etmek istiyorsanız, aşağıdaki gibi bir şeye ihtiyacınız vardır. Ayrıca bu komutta test verilerini eklemeyi birleştiriyorum:

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

Yapabilmek güzel olurdu, cursor.execute(call_command('sqlclear', 'main'))ancak call_commandSQL'i bir dizge olarak döndürmek yerine standart çıktıya yazdırıyor ve sql_deletekodu çözemiyorum ...


Güzel USE DATABASEBen SQLite3 et PostgreSQL arasında geçiş yapmak için ayarlara dayalı hangi irade oto anahtarı bir yönetim komutuyla bir django-Tekrar Oluştur-db paket oluşturmak için size salık vermek.
Natim

4

İşte bu sorunu çözmek için bir araya getirdiğim bir kabuk betiği. Umarım birine biraz zaman kazandırır.

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

2

Komut ./manage.py sqlclearveya ./manage.py sqlflushtamamladıktan veritabanı bunu deneyin silmek istiyor ancak eğer bunları silmek tablo temizlemek değil gibi görünüyor: manage.py flush.

Uyarı: Bu, veritabanınızı tamamen silecek ve tüm verilerinizi kaybedeceksiniz, bu yüzden önemli değilse, devam edin ve deneyin.


2
Hayır, bu yanlış. flush ve sqlflush aynıdır, tüm verileri kaldırır, ancak tabloları düşürmez. sqlflush, sql'yi görüntüler, ancak yürütmez, flush bunu görüntülemeden yürütür.
Moulde

1

Bir flushproject komutu oluşturmak için Python kullanarak şunları kullanırsınız:

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

Sorum, veritabanı zaten mevcut değilse bunun nasıl gerçekleştirileceği?
Natim

Maalesef aynı komut dosyasındaki herhangi bir başka işlem (örneğin syncdb) "Veritabanı seçilmedi" hatalarıyla sonuçlanır.
Timmmm

Bir komut verdi flushdbve başka bir komut başlattıktan sonra. başka bir komut dosyasında ihtiyacınız varsa, şunu kullanabilirsinizcall_command
Natim

Ben takip etmiyorum Ben zaten kullanıyorum call_command. Daha call_command("flushdb")önce yapmam gerektiğini call_command("syncdb")mi söylüyorsun ?
Timmmm

Çalışmıyor. Aynı hata. Hata "Veritabanı seçilmedi" olduğundan herhangi bir SQL yürütemezsiniz . Çözümü buldum: Diğer cevabıma bakın.
Timmmm

1

İşte birden çok ayar dosyasıyla bazı güzel şeyler yapmak için bir Makefile örneği:

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

O zaman aşağıdaki gibi şeyler yapabilirsiniz: $ make db_reset


1

Bu cevap postgresql DB içindir:

Çalıştır: echo ' bazı_kullanıcıya ait drop ' | ./manage.py dbshell

NOT: bazı_kullanıcılar , veritabanına erişmek için kullandığınız kullanıcının adıdır, bkz. Settings.py dosyası:

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

1

Psql kullanıyorsanız ve django-more 2.0.0 yüklüyse, şunları yapabilirsiniz:

manage.py reset_schema


0

İşte @ peter-g'nin cevabının güneye göç versiyonu. Sık sık ham sql ile oynarım, bu yüzden bu, karışık uygulamalar için 0001_initial.py olarak kullanışlıdır. Yalnızca destekleyen DB'lerde çalışır SHOW TABLES(mysql gibi). SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';PostgreSQL kullanıyorsanız, bunun yerine bir şey koyun. Ayrıca, sık sık her ikisi için bu da aynı işi görüyor forwardsve backwardsgöçler.

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

İş arkadaşları / kodlayıcılar, bunu yaptığımı bilselerdi beni öldürürdü.


0

TÜM tablolarınızı silmek istiyorsanız daha da basit bir cevap var. Veritabanını (veritabanım.db olarak adlandırılabilir) içeren klasörünüze gidin ve .db dosyasına sağ tıklayın ve "sil" seçeneğine basın. Eski moda yol, kesinlikle işe yarayacak.


2
Sadece sqlite veritabanları için :-)
winwa

0

Tüm tabloları bırakır ve yeniden oluşturur:

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

Açıklama:

manage.py sqlclear - "verilen uygulama adları için DROP TABLE SQL deyimlerini yazdırır"

sed -n "2,$p" - ilk satır hariç tüm hatları yakalar

sed -n "$ !p" - son satır hariç tüm hatları yakalar

sed "s/";/" CASCADE;/" - tüm noktalı virgülleri (;) (CASCADE;) ile değiştirir

sed -e "1s/^/BEGIN;/" -e "$s/$/COMMIT;/" - ilk metin olarak ekler (BEGIN;), son metin olarak ekler (COMMIT;)

manage.py dbshell - "ENGINE ayarınızda belirtilen veritabanı motoru için komut satırı istemcisini KULLANICI, PAROLA, vb. Ayarlarınızda belirtilen bağlantı parametreleriyle çalıştırır"

manage.py syncdb - "INSTALLED_APPS içindeki tabloları henüz oluşturulmamış tüm uygulamalar için veritabanı tabloları oluşturur"

Bağımlılıklar:


Kredi:

@Manoj Govindan ve @Mike DeSimone sqlclear için dbshell'e aktarıldı

'sed "s /"; / "CASCADE; /"' için @jpic



Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.