ฉันได้ทำการย้ายข้อมูลที่เพิ่มตารางใหม่และต้องการเปลี่ยนกลับและลบการย้ายข้อมูลโดยไม่ต้องสร้างการย้ายข้อมูลใหม่
ฉันต้องทำอย่างไร? มีคำสั่งให้ยกเลิกการย้ายข้อมูลครั้งล่าสุดแล้วฉันสามารถลบไฟล์การโยกย้ายได้หรือไม่
ฉันได้ทำการย้ายข้อมูลที่เพิ่มตารางใหม่และต้องการเปลี่ยนกลับและลบการย้ายข้อมูลโดยไม่ต้องสร้างการย้ายข้อมูลใหม่
ฉันต้องทำอย่างไร? มีคำสั่งให้ยกเลิกการย้ายข้อมูลครั้งล่าสุดแล้วฉันสามารถลบไฟล์การโยกย้ายได้หรือไม่
คำตอบ:
คุณสามารถเปลี่ยนกลับได้โดยย้ายไปใช้การโยกย้ายครั้งก่อน
ตัวอย่างเช่นหากการโยกย้ายสองครั้งสุดท้ายของคุณคือ:
0010_previous_migration
0011_migration_to_revert
จากนั้นคุณจะทำ:
./manage.py migrate my_app 0010_previous_migration
0011_migration_to_revert
จากนั้นคุณสามารถลบการโยกย้าย
หากคุณใช้ Django 1.8+ คุณสามารถแสดงชื่อของการย้ายข้อมูลทั้งหมดด้วย
./manage.py showmigrations my_app
หากต้องการย้อนกลับการโยกย้ายทั้งหมดสำหรับแอปคุณสามารถเรียกใช้:
./manage.py migrate my_app zero
'0010_previous_migration'
ฉันไม่รู้ว่าทำไมคุณจะเห็นพฤติกรรมนั้น
คำตอบโดย Alasdair ครอบคลุมพื้นฐาน
./manage.py showmigrations
migrate
ใช้ชื่อแอพและชื่อการย้ายข้อมูลแต่ควรชี้ให้เห็นว่าการย้ายข้อมูลบางอย่างไม่สามารถย้อนกลับได้ สิ่งนี้จะเกิดขึ้นหาก Django ไม่มีกฎในการกลับรายการ สำหรับการเปลี่ยนแปลงส่วนใหญ่ที่คุณทำการโอนย้ายโดยอัตโนมัติภายใน./manage.py makemigrations
การกลับรายการจะเป็นไปได้ อย่างไรก็ตามสคริปต์ที่กำหนดเองจะต้องมีทั้งการเขียนไปข้างหน้าและย้อนกลับดังที่อธิบายไว้ในตัวอย่างที่นี่:
https://docs.djangoproject.com/en/1.9/ref/migration-operations/
หากคุณมีการRunPython
ดำเนินการบางทีคุณอาจต้องการสำรองข้อมูลการย้ายข้อมูลโดยไม่ต้องเขียนสคริปต์การกลับรายการที่เข้มงวดอย่างมีเหตุผล แฮ็คด่วนต่อไปนี้เป็นตัวอย่างจาก docs (ลิงก์ด้านบน) อนุญาตให้ทำเช่นนี้ปล่อยให้ฐานข้อมูลอยู่ในสถานะเดียวกับที่มันเกิดขึ้นหลังจากการย้ายข้อมูลถูกนำไปใช้แม้ว่าจะย้อนกลับไปแล้วก็ตาม
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
def forwards_func(apps, schema_editor):
# We get the model from the versioned app registry;
# if we directly import it, it'll be the wrong version
Country = apps.get_model("myapp", "Country")
db_alias = schema_editor.connection.alias
Country.objects.using(db_alias).bulk_create([
Country(name="USA", code="us"),
Country(name="France", code="fr"),
])
class Migration(migrations.Migration):
dependencies = []
operations = [
migrations.RunPython(forwards_func, lambda apps, schema_editor: None),
]
ใช้งานได้กับ Django 1.8, 1.9
อัปเดต: วิธีที่ดีกว่าในการเขียนสิ่งนี้คือแทนที่lambda apps, schema_editor: None
ด้วยmigrations.RunPython.noop
ในข้อมูลโค้ดด้านบน สิ่งเหล่านี้ทั้งสองเป็นสิ่งเดียวกัน (เครดิตกับความคิดเห็น)
RunPython.noop
แทนแลมบ์ดาแบบอินไลน์หรือequivelent
migrations.RunPython(forwards_func, migrations.RunPython.noop)
ในไวยากรณ์ของตัวอย่างที่ผมคิดว่ามีลักษณะเหมือน จำเป็นต้องตรวจสอบว่าใช้งานได้จริง ที่ควรได้รับการเพิ่มเป็นคำตอบหรือแก้ไขหนึ่งนี้บางครั้ง
RunPython
นี่คือวิธีการแก้ปัญหาของฉันตั้งแต่วิธีการแก้ปัญหาดังกล่าวข้างต้นไม่ได้จริงๆครอบคลุมการใช้งานในกรณีที่เมื่อคุณใช้
คุณสามารถเข้าถึงตารางผ่าน ORM ด้วย
from django.db.migrations.recorder import MigrationRecorder
>>> MigrationRecorder.Migration.objects.all()
>>> MigrationRecorder.Migration.objects.latest('id')
Out[5]: <Migration: Migration 0050_auto_20170603_1814 for model>
>>> MigrationRecorder.Migration.objects.latest('id').delete()
Out[4]: (1, {u'migrations.Migration': 1})
ดังนั้นคุณสามารถค้นหาตารางและลบรายการที่เกี่ยวข้องกับคุณได้ วิธีนี้คุณสามารถแก้ไขรายละเอียดได้ ด้วยการRynPython
โยกย้ายคุณยังต้องดูแลข้อมูลที่ถูกเพิ่ม / เปลี่ยนแปลง / ลบออก ตัวอย่างด้านบนแสดงเฉพาะวิธีที่คุณเข้าถึงตารางผ่าน Djang ORM
django.db.utils.ProgrammingError: relation "<relation name>" already exists
นั้นฉันทำmigrate --fake
ผิดซึ่งฉันพยายามกลับไปอีกครั้งจากนั้นฉันก็psycopg2.ProgrammingError: relation "<other <relation name>" does not exist
ขอขอบคุณ
สิ่งอื่น ๆ ที่คุณสามารถทำได้คือลบตารางที่สร้างขึ้นด้วยตนเอง
นอกจากนั้นคุณจะต้องลบไฟล์การโยกย้ายนั้น ๆ นอกจากนี้คุณจะต้องลบรายการนั้นในตาราง django-migrations (อาจเป็นรายการสุดท้ายในกรณีของคุณ) ซึ่งสัมพันธ์กับการโยกย้ายนั้น
อย่าลบไฟล์การโยกย้ายจนกว่าหลังจากการพลิกกลับ ฉันทำผิดพลาดและไม่มีไฟล์การโยกย้ายฐานข้อมูลไม่ทราบว่าจะลบอะไรออก
python manage.py showmigrations
python manage.py migrate {app name from show migrations} {00##_migration file.py}
ลบไฟล์การโยกย้าย เมื่อการโยกย้ายที่ต้องการอยู่ในแบบจำลองของคุณ ...
python manage.py makemigrations
python manage.py migrate
ฉันทำสิ่งนี้ใน 1.9.1 (เพื่อลบการย้ายข้อมูลล่าสุดหรือสร้างล่าสุด):
rm <appname>/migrations/<migration #>*
ตัวอย่าง: rm myapp/migrations/0011*
ล็อกอินเข้าสู่ฐานข้อมูลและรัน SQL นี้ (postgres ในตัวอย่างนี้)
delete from django_migrations where name like '0011%';
ฉันสามารถสร้างการย้ายข้อมูลใหม่ที่เริ่มต้นด้วยหมายเลขการย้ายข้อมูลที่ฉันเพิ่งลบไป (ในกรณีนี้คือ 11)
คำตอบนี้เป็นกรณีที่คล้ายกันถ้าคำตอบด้านบนโดย Alasdair ไม่ได้ช่วย (เช่นหากการย้ายข้อมูลที่ไม่ต้องการถูกสร้างขึ้นอีกครั้งในทุกครั้งที่มีการย้ายข้อมูลใหม่หรืออยู่ในการย้ายข้อมูลที่ใหญ่กว่าซึ่งไม่สามารถเปลี่ยนกลับได้หรือตารางถูกลบด้วยตนเอง)
... ลบการย้ายข้อมูลโดยไม่สร้างการย้ายข้อมูลใหม่หรือไม่
TL; DR : คุณสามารถลบไม่กี่สุดท้ายหวนกลับ (สับสน) การโยกย้ายและสร้างใหม่หลังจากแก้ไขรุ่น คุณยังสามารถใช้วิธีอื่นเพื่อกำหนดค่าให้ไม่สร้างตารางโดยคำสั่งโยกย้าย การโยกย้ายที่ผ่านมาจะต้องสร้างขึ้นเพื่อให้ตรงกับรุ่นปัจจุบัน
กรณีที่ทำไมทุกคนไม่ต้องการสร้างตารางสำหรับแบบจำลองที่ต้องมีอยู่:
A)ไม่ควรมีตารางดังกล่าวในฐานข้อมูลที่ไม่มีในเครื่องและไม่มีเงื่อนไข
class Meta: abstract = True
B)ตารางถูกสร้างขึ้นไม่ค่อยมีอย่างอื่นหรือด้วยตนเองในวิธีพิเศษ
class Meta: managed = False
C)ตารางนี้ใช้กับเครื่องบางเครื่องเท่านั้น (เช่นในการพัฒนา)
class Meta: managed = some_switch
เฉพาะภายใต้เงื่อนไขพิเศษหรือใช้เงื่อนไขD)โครงการใช้หลายฐานข้อมูลในsettings.DATABASES
allow_migrate
เพื่อแยกความแตกต่างของฐานข้อมูลที่ควรสร้างตารางและตำแหน่งที่ไม่การโยกย้ายถูกสร้างขึ้นในทุกกรณี A), B), C), D) กับ Django 1.9+ (และเฉพาะในกรณี B, C, D กับ Django 1.8) แต่นำไปใช้กับฐานข้อมูลเฉพาะในกรณีที่เหมาะสมหรืออาจไม่เคยถ้า จำเป็นต้องใช้ดังนั้น การย้ายจำเป็นสำหรับการทดสอบตั้งแต่ Django 1.8 สถานะปัจจุบันที่เกี่ยวข้องทั้งหมดจะถูกบันทึกโดยการย้ายข้อมูลแม้สำหรับรุ่นที่มีการจัดการ = False ใน Django 1.9+ เพื่อเป็นไปได้ในการสร้าง ForeignKey ระหว่างรุ่นที่มีการจัดการ / ไม่มีการจัดการหรือเพื่อให้สามารถจัดการรูปแบบ = True ในภายหลัง (คำถามนี้เขียนขึ้นในช่วงเวลาของ Django 1.8 ทุกอย่างที่นี่ควรจะใช้ได้สำหรับรุ่นระหว่าง 1.8 ถึงปัจจุบัน 2.2)
หากการโยกย้ายครั้งล่าสุดคือ (เป็น) ไม่สามารถย้อนกลับได้อย่างง่ายดายก็เป็นไปได้ที่จะระมัดระวัง (หลังจากการสำรองฐานข้อมูล) ทำการเปลี่ยนกลับปลอม ./manage.py migrate --fake my_app 0010_previous_migration
ให้ลบตารางด้วยตนเอง
./manage.py migrate --fake my_app 0011_fixed_migration
หากจำเป็นต้องสร้างการโยกย้ายคงที่จากรูปแบบคงที่และใช้มันโดยไม่ต้องเปลี่ยนโครงสร้างฐานข้อมูล
หากคุณกำลังประสบปัญหาในขณะที่คืนค่าการย้ายข้อมูลกลับมาและทำให้เกิดความสับสนคุณสามารถทำการfake
ย้ายข้อมูลได้
./manage.py migrate <name> --ignore-ghost-migrations --merge --fake
สำหรับdjango เวอร์ชัน <1.7สิ่งนี้จะสร้างรายการในsouth_migrationhistory
ตารางคุณต้องลบรายการนั้น
ตอนนี้คุณจะสามารถย้อนกลับการโยกย้ายได้อย่างง่ายดาย
PS: ฉันติดอยู่เป็นเวลานานและทำการย้ายถิ่นของปลอมแล้วการคืนค่ากลับช่วยฉันออก