วิธีวางตารางทั้งหมดจากฐานข้อมูลด้วย Manage.py CLI ใน Django


95

ฉันจะวางตารางทั้งหมดจากฐานข้อมูลโดยใช้ Manage.py และ command line ได้อย่างไร มีวิธีใดบ้างที่จะดำเนินการ Manage.py ด้วยพารามิเตอร์ที่เหมาะสมเพื่อให้ฉันสามารถเรียกใช้งานจากแอปพลิเคชัน. NET ได้

คำตอบ:


128

เท่าที่ฉันรู้ไม่มีคำสั่งการจัดการเพื่อวางตารางทั้งหมด หากคุณไม่สนใจที่จะแฮ็ก Python คุณสามารถเขียนคำสั่งของคุณเองเพื่อทำเช่นนั้น คุณอาจพบว่าsqlclearตัวเลือกนี้น่าสนใจ เอกสารระบุว่า./manage.py sqlclear พิมพ์คำสั่ง DROP TABLE SQL สำหรับชื่อแอพที่กำหนด

อัปเดต : ใส่ความคิดเห็นของ@Mike DeSimoneอย่างไร้ยางอายใต้คำตอบนี้เพื่อให้คำตอบที่สมบูรณ์

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

ของ django 1.9 ตอนนี้ ./manage.py sqlflush


sqlclear "พิมพ์คำสั่งวาง" แต่จะดำเนินการอย่างไรในการเรียกบรรทัดคำสั่งเดียว
kmalmur

3
คุณต้องมีชื่อแอปเช่น:./manage.py sqlclear myAppName | ./manage.py dbshell
Montaro

4
นี่ใช้ไม่ได้เลย sqlclear ต้องการชื่อแอป ฉันใช้ Django 1.8
Jonathan Hartley

1
โปรดทราบว่า sqlflush ไม่วางตาราง แต่จะตัดทอนพวกเขา นอกจากนี้การดำเนินการนี้อาจใช้ไม่ได้กับ postgresql DB ของคุณเว้นแต่คุณจะเพิ่มคีย์เวิร์ด CASCADE ที่ท้ายคำสั่งตัดทอนที่สร้างโดย sqlflush
user3748764

39

ไม่มีคำสั่งจัดการ Django ดั้งเดิมที่จะวางตารางทั้งหมด ทั้งสองอย่างsqlclearและresetต้องใช้ชื่อแอป

อย่างไรก็ตามคุณสามารถติดตั้งDjango Extensionsซึ่งให้manage.py reset_dbสิ่งที่คุณต้องการ (และให้คุณเข้าถึงคำสั่งการจัดการที่มีประโยชน์อื่น ๆ อีกมากมาย )


@JulienGreard อัปเดต ขอบคุณ!
Anuj Gupta

4
ฉันล้มเลิกความพยายามและใช้สิ่งนี้
laffuste

สิ่งนี้ได้ผลสำหรับฉันในขณะที่ไม่มีคำตอบใดที่มีอันดับสูงกว่า
Jonathan Hartley

1
@AnujGupta มัก manage.py reset_dbต้องการแฟล็ก `-c, --close-sessions` เพื่อปิดการเชื่อมต่อฐานข้อมูลก่อนที่จะทิ้งฐานข้อมูล (PostgreSQL เท่านั้น)
Valery Ramusik

34

หากคุณใช้แพ็คเกจ South เพื่อจัดการการย้ายฐานข้อมูล (แนะนำเป็นอย่างยิ่ง) คุณสามารถใช้./manage.py migrate appname zeroคำสั่งได้

มิฉะนั้นฉันขอแนะนำ./manage.py dbshellคำสั่งการวางท่อในคำสั่ง SQL ในอินพุตมาตรฐาน


+1. โครงการ Django ที่ไม่สำคัญใด ๆ ควรใช้ทิศใต้ และเมื่อคุณใช้ South แล้วการย้ายไปที่ Zero เป็นวิธีที่ดีในการวางตารางทั้งหมด
Manoj Govindan

แม้แต่โครงการ Django ที่ไม่สำคัญก็ควรพิจารณาภาคใต้ เพียงเพื่อให้ผู้คนคุ้นเคยกับการย้ายฐานข้อมูลดังนั้นพวกเขาจึงไม่ได้เรียนรู้นิสัยที่ไม่ดีเช่นการพยายามทิ้งแฮ็กและโหลดข้อมูลซ้ำด้วยมือหรือใช้กลไกการติดตั้งเพื่อย้ายข้อมูล
Mike DeSimone

ฉันใช้ South แต่ฉันไม่ต้องกังวลกับการเขียนการย้ายข้อมูลย้อนกลับสำหรับการย้ายข้อมูลทุกครั้ง: ไม่ใช่อย่างน้อยการย้ายข้อมูล และฉันจะไม่ทำอย่างนั้นเพื่อที่ฉันจะได้ใช้ตัวเลือกศูนย์ แน่นอนว่าเป็นวิธีที่ดีในการทดสอบว่าคุณ / สามารถ / ถอยหลังกลับเป็นศูนย์ได้หากนั่นสำคัญสำหรับคุณ การทิ้งโต๊ะทั้งหมดดูสมเหตุสมผลสำหรับฉัน
tobych

26

python manage.py migrate <app> zero

sqlclear ถูกลบออกจาก 1.9

บันทึกประจำรุ่นระบุว่าเกิดจากการแนะนำการย้ายข้อมูล: https://docs.djangoproject.com/en/1.9/releases/1.9/

น่าเสียดายที่ฉันไม่พบวิธีการที่ใช้ได้กับแอพทั้งหมดในคราวเดียวหรือวิธีในตัวในการแสดงรายการแอพที่ติดตั้งทั้งหมดจากผู้ดูแลระบบ: จะแสดงรายการแอพที่ติดตั้งทั้งหมดด้วย Manage.py ใน Django ได้อย่างไร

ที่เกี่ยวข้อง: จะรีเซ็ตการย้ายข้อมูลใน Django 1.7 ได้อย่างไร


12

ใช้ดีกว่า./manage.py sqlflush | ./manage.py dbshellเพราะ sqlclear ต้องใช้แอพในการล้าง


7

วิธีง่ายๆ (?) ในการทำจาก 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)

5

หากคุณต้องการล้างฐานข้อมูลทั้งหมดและซิงค์ใหม่ในครั้งเดียวกันคุณต้องมีสิ่งต่อไปนี้ ฉันยังรวมการเพิ่มข้อมูลการทดสอบในคำสั่งนี้:

#!/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 เป็น stdout แทนที่จะส่งคืนเป็นสตริงและฉันไม่สามารถหาsql_deleteรหัสได้ ...


ดีมากUSE DATABASEฉันขอแนะนำให้คุณสร้างแพ็คเกจ django-create-db ด้วยคำสั่งการจัดการซึ่งจะสลับอัตโนมัติตามการตั้งค่าเพื่อสลับระหว่าง SQLite3 et PostGresql
Natim

4

นี่คือเชลล์สคริปต์ที่ฉันสรุปเข้าด้วยกันเพื่อจัดการกับปัญหานี้ หวังว่าจะช่วยใครบางคนได้บ้าง

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

การใช้ 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']])

คำถามของฉันคือจะดำเนินการอย่างไรหากไม่มีฐานข้อมูลอยู่แล้ว
Natim

น่าเศร้าที่การดำเนินการเพิ่มเติมในสคริปต์เดียวกัน (เช่น syncdb) ทำให้เกิดข้อผิดพลาด "ไม่ได้เลือกฐานข้อมูล"
Timmmm

มันทำคำสั่งflushdbและหลังจากที่ฉันเปิดคำสั่งอื่น ถ้าคุณต้องการในสคริปต์อื่นคุณอาจใช้call_command
Natim

ฉันไม่ทำตาม call_commandฉันกำลังใช้อยู่แล้ว คุณกำลังบอกว่าฉันควรทำcall_command("flushdb")ก่อนcall_command("syncdb")?
Timmmm

ไม่ทำงาน ข้อผิดพลาดเดียวกัน ข้อผิดพลาดคือ "ฐานข้อมูลไม่ได้เลือก" ดังนั้นคุณจึงไม่สามารถดำเนินการใด ๆ SQL พบวิธีแก้ปัญหา: ดูคำตอบอื่นของฉัน
Timmmm

1

คำสั่ง./manage.py sqlclearหรือ./manage.py sqlflushดูเหมือนว่าจะล้างตารางและไม่ลบออก manage.py flushแต่ถ้าคุณต้องการลบฐานข้อมูลที่สมบูรณ์ลองนี้

คำเตือน: การดำเนินการ นี้จะลบฐานข้อมูลของคุณโดยสิ้นเชิงและคุณจะสูญเสียข้อมูลทั้งหมดดังนั้นหากไม่สำคัญให้ดำเนินการต่อและลองใช้


2
ไม่นี่ไม่ถูกต้อง flush และ sqlflush เหมือนกันจะลบข้อมูลทั้งหมด แต่ไม่วางตาราง sqlflush แสดง sql แต่ไม่ได้ดำเนินการล้างจะดำเนินการโดยไม่ต้องแสดง
Moulde

1

นี่คือตัวอย่าง 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


1

คำตอบนี้มีไว้สำหรับ 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': '',
}


0

นี่คือคำตอบของ @ peter-g เวอร์ชันอพยพทางใต้ ฉันมักจะเล่นกับ sql แบบดิบดังนั้นสิ่งนี้จึงมีประโยชน์ในฐานะ 0001_initial.py สำหรับแอปที่สับสน จะใช้ได้เฉพาะกับฐานข้อมูลที่รองรับSHOW TABLES(เช่น mysql) แทนที่บางอย่างเช่นSELECT table_name FROM information_schema.tables WHERE table_schema = 'public';ถ้าคุณใช้ PostgreSQL นอกจากนี้ฉันมักจะทำสิ่งนี้เหมือนกันกับทั้งการย้ายข้อมูล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()))

เพื่อนร่วมงาน / เพื่อนร่วมงานจะฆ่าฉันถ้าพวกเขารู้ว่าฉันทำแบบนี้


0

มีคำตอบที่ง่ายกว่านี้หากคุณต้องการลบตารางทั้งหมด คุณเพียงไปที่โฟลเดอร์ของคุณที่มีฐานข้อมูล (ซึ่งอาจเรียกว่า mydatabase.db) แล้วคลิกขวาที่ไฟล์. db แล้วกด "ลบ" วิธีการแบบเก่าทำงานได้อย่างแน่นอน


1
สำหรับฐานข้อมูล sqlite เท่านั้น :-)
winwaed

0

วางตารางทั้งหมดและสร้างใหม่:

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 รหัสผ่าน ฯลฯ "

manage.py syncdb - "สร้างตารางฐานข้อมูลสำหรับแอปทั้งหมดใน INSTALLED_APPS ที่ยังไม่ได้สร้างตาราง"

การพึ่งพา:


เครดิต:

@Manoj Govindan และ @Mike DeSimone สำหรับ sqlclear piped ไปยัง dbshell

@jpic สำหรับ 'sed "s /"; / "CASCADE; /"'



โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.