วิธีที่แนะนำในการรีเซ็ตประวัติการย้ายข้อมูลโดยใช้ Django South คืออะไร


153

ฉันสะสมการโยกย้ายข้อมูลค่อนข้างน้อยโดยใช้ South (0.7) และ Django (1.1.2) ซึ่งเริ่มใช้เวลาในการทดสอบหน่วยเล็กน้อย ฉันต้องการรีเซ็ตพื้นฐานและเริ่มชุดการโยกย้ายใหม่ ฉันได้ตรวจสอบเอกสารภาคใต้แล้วทำการค้นหาใน Google / Stackoverflow ตามปกติ (เช่น "django south (รีเซ็ตหรือลบหรือลบ) ประวัติการย้ายข้อมูล") และไม่พบสิ่งใดที่ชัดเจน

วิธีการหนึ่งที่ฉันได้ไตร่ตรองไว้นั้นจะเกี่ยวข้องกับ "การเริ่มต้นใหม่" โดย "การลบ" South หรือ "การล้าง" ประวัติด้วยตนเอง (เช่นล้างตาราง db ลบไฟล์การโยกย้ายจากผู้กำกับการย้ายข้อมูล) และเพียงเรียกใช้อีกครั้ง

./manage.py schemamigration southtut --initial

ดังนั้นหากใครเคยทำมาก่อนและมีเคล็ดลับ / ข้อเสนอแนะพวกเขาจะได้รับการชื่นชมอย่างมาก


บางครั้งคุณต้องเพิ่มด้วยตนเอง__init__.pyไปappname/migrations
laike9m

2
คุณรีเซ็ตการโยกย้ายใน 1.7 (ด้วยการโยกย้ายในตัว) ได้อย่างไร
Timo

1
@Timo: docs.djangoproject.com/th/dev/topics/migrations/…อาจเป็นวิธีการ นอกจากนี้คุณยังสามารถลบการย้าย /ไดเรกทอรีและออกใหม่./manage.py makemigrationsแต่สิ่งเลวร้ายจะเกิดขึ้นหากคุณไม่ได้เริ่มต้นจากฐานข้อมูลใหม่ ...
Jocelyn delalande

ฉันคิดว่าsquashmigrationsเป็นคำตอบที่ถูกต้อง
Julio Marins

คำตอบ:


121

แก้ไข - ฉันใส่ความคิดเห็นด้านล่างที่ด้านบนของสิ่งนี้เป็นสิ่งสำคัญที่จะอ่านก่อนคำตอบที่ได้รับการยอมรับที่ตาม @andybak

@Dominique: คำแนะนำของคุณเกี่ยวกับ Manage.py รีเซ็ตทางทิศใต้เป็นสิ่งที่อันตรายและอาจทำลายฐานข้อมูลหากมีแอพของบุคคลที่สามที่ใช้งานทางทิศใต้ในโครงการตามที่ระบุไว้โดย @thnee ด้านล่าง เนื่องจากคำตอบของคุณมี upvotes มากมายฉันขอขอบคุณถ้าคุณสามารถแก้ไขและเพิ่มคำเตือนเกี่ยวกับสิ่งนี้หรืออย่างน้อย (หรือดีกว่า) ให้เปลี่ยนเป็นวิธี @hobs (ซึ่งสะดวกมาก แต่ไม่สะดวก ส่งผลกระทบต่อแอพอื่น ๆ ) - ขอบคุณ! - chrisv 26 มีนาคม '13 ที่ 9:09

คำตอบที่ได้รับการยอมรับดังต่อไปนี้:

ก่อนคำตอบโดยผู้เขียนใต้ :

ตราบใดที่คุณระมัดระวังในการปรับใช้ทั้งหมดพร้อมกันไม่ควรมีปัญหาใด ๆ กับสิ่งนี้ ส่วนตัวฉันจะทำ:

    rm -r appname/migrations/ 
    ./manage.py reset south 
    ./manage.py convert_to_south appname 

(ขอให้สังเกตว่าreset south ” จะทำการล้างข้อมูลบันทึกการย้ายข้อมูลสำหรับแอพทั้งหมดดังนั้นตรวจสอบให้แน่ใจว่าคุณได้รันอีกสองบรรทัดสำหรับแอพทั้งหมดหรือลบแบบเลือก)

การconvert_to_southโทรท้ายทำให้การย้ายข้อมูลใหม่และใช้การปลอม (เนื่องจากฐานข้อมูลของคุณมีตารางที่เกี่ยวข้องอยู่แล้ว) ไม่จำเป็นต้องวางตารางแอปทั้งหมดในระหว่างกระบวนการ

นี่คือสิ่งที่ฉันทำบนเซิร์ฟเวอร์ dev + production ของฉันเมื่อฉันต้องการกำจัดการโยกย้าย dev ที่ไม่จำเป็นเหล่านี้:

  1. ตรวจสอบให้แน่ใจว่าเรามี DB schema เดียวกันทั้งสองด้าน
  2. ลบทุกโฟลเดอร์การย้ายข้อมูลทั้งสองด้าน
  3. run ./manage.py รีเซ็ตทิศใต้ (ตามที่โพสต์บอกว่า) ทั้งสองด้าน = ล้างตารางใต้ *
  4. run ./manage.py convert_to_southทั้งสองด้าน (แกล้งทำ 0001 การย้าย)
  5. จากนั้นฉันสามารถเริ่มต้นอีกครั้งเพื่อทำการย้ายข้อมูลและผลักดันโฟลเดอร์การย้ายข้อมูลบนเซิร์ฟเวอร์ของฉัน

* ยกเว้นถ้าคุณต้องการล้างแอพเดียวในแอปอื่นถ้าใช่คุณจะต้องแก้ไขตาราง south_history ของคุณและลบเฉพาะรายการที่เกี่ยวกับแอปของคุณ


2
เพียงเพื่อบันทึกการตอบสนองของผู้เขียนใต้มีดังนี้: ตราบใดที่คุณระมัดระวังในการปรับใช้ทั้งหมดพร้อมกันไม่ควรมีปัญหาใด ๆ กับสิ่งนี้ โดยส่วนตัวแล้วฉันจะทำ: rm -r appname / migrations / ./manage.py รีเซ็ตทิศใต้ / manage.py convert_to_south ชื่อแอป (โปรดสังเกตว่าส่วน "รีเซ็ตทิศใต้" จะล้างบันทึกการย้ายข้อมูลสำหรับแอปทั้งหมดดังนั้นให้แน่ใจว่าคุณใช้ อีกสองบรรทัดสำหรับแอพทั้งหมดหรือลบรายการที่เลือก)
Adriaan Tijsseling

2
โปรดทราบว่าหากคุณวางตารางคุณจะต้องmanage.py schemamigration app name --initialเปลี่ยน convert_to_south
Adriaan Tijsseling

7
ตั้งแต่ Django 1.5 คำสั่งการจัดการ "รีเซ็ต" หายไป แต่คุณจะต้องการที่จะทำบางสิ่งบางอย่างคร่าว ๆ south.models.MigrationHistory.objects.all().delete()เช่น
Andrew B.

13
@Dominique: คำแนะนำของคุณเกี่ยวกับการmanage.py reset southเป็นอันตรายและอาจทำลายฐานข้อมูลหากมีปพลิเคชันของบุคคลที่สามโดยใช้ภาคใต้ในโครงการเช่นการชี้โดย @thnee ด้านล่าง เนื่องจากคำตอบของคุณมี upvotes มากมายฉันขอขอบคุณถ้าคุณสามารถแก้ไขและเพิ่มคำเตือนเกี่ยวกับสิ่งนี้หรืออย่างน้อย (หรือดีกว่า) ให้เปลี่ยนเป็นวิธี @hobs (ซึ่งสะดวกมาก แต่ไม่สะดวก ส่งผลกระทบต่อแอพอื่น ๆ ) - ขอบคุณ!
chrisv

3
เหตุใดจึงมีการปรับตัวสูงขึ้นอย่างมาก? คุณไม่ควรลบตาราง south_migrationhistory ของคุณอย่างสมบูรณ์ นั่นจะทำให้แอพที่ขึ้นต่อกันหมดสิ้นลงด้วยการย้ายข้อมูลที่คุณไม่ต้องการแตะ คำตอบของ Hob คือคำตอบที่ถูกต้อง
Cerin

188

หากคุณต้องการเลือก (สำหรับแอปเดียว) ให้ทำการย้ายข้อมูลที่ใช้เวลานานเกินไป สิ่งนี้ใช้ได้สำหรับฉัน

rm <app-dir>/migrations/*
python manage.py schemamigration <app-name> --initial
python manage.py migrate <app-name> 0001 --fake  --delete-ghost-migrations

อย่าลืมเรียกคืนด้วยตนเอง พึ่งพาๆ ของแอพอื่น ๆโดยเพิ่มบรรทัดที่ชอบdepends_on = (("<other_app_name>", "0001_initial"),("<yet_another_app_name>", "0001_initial"))ลงใน<app-dir>/migrations/0001_initial.pyไฟล์ของคุณเนื่องจากเป็นแอททริบิวแรกในคลาสการย้ายข้อมูลของคุณด้านล่างclass Migration(SchemaMigration):ไฟล์เป็นแอตทริบิวต์ในชั้นแรกย้ายข้อมูลเพียงด้านล่าง

จากนั้นคุณสามารถ./manage.py migrate <app-name> --fake --delete-ghost-migrationsในสภาพแวดล้อมอื่น ๆ ต่อคำตอบ SO นี้ แน่นอนถ้าคุณปลอมลบหรือปลอมmigrate zeroคุณจะต้องลบตาราง db ซ้ายไปด้วยตนเองด้วยการโยกย้ายเช่นนี้นี้

ตัวเลือกนิวเคลียร์เพิ่มเติมคือ./manage.py migrate --fake --delete-ghost-migrationsบนเซิร์ฟเวอร์การปรับใช้สดตามด้วย sqldump [ของฉัน] จากนั้นไพพ์ที่ดัมพ์ลงใน [my] sql บนสภาวะแวดล้อมที่คุณต้องการฐานข้อมูลที่ถูกย้ายข้อมูล ฉันรู้ว่าใต้ความศักดิ์สิทธิ์ แต่ทำงานเพื่อฉัน


2
สิ่งที่ฉันต้องการคือ "เอา models.py เป็นข่าวประเสริฐและทำให้ฉันสะอาดจากจุดนั้นไป" ดังนั้นการรักษาความสามารถในการตั้งค่าการปรับใช้จากรอยขีดข่วนหรือทำงานจากการปรับใช้ที่มีอยู่
ไบรซ์

1
นั่นคือสิ่งที่ทำ
hobs

2
@hobs ฉันได้รับDependsOnUnknownMigrationในขณะที่แกล้งทำการโยกย้ายครั้งแรกใหม่ ขอบคุณที่แสดงความคิดเห็นของคุณฉันสามารถคิดได้ว่าฉันควรปรับปรุงdepends_onคำสั่งทุกที่ที่อ้างถึงแอพนี้ นี่เป็นคำตอบที่ดีที่สุดที่นี่จริงๆ ขอบคุณ! :)
มนู

55

ขอบคุณคำตอบของ Dominique Guardiola และเตาทำอาหารช่วยฉันแก้ปัญหาอย่างหนัก อย่างไรก็ตามมีปัญหาสองสามข้อเกี่ยวกับการแก้ไขนี่คือสิ่งที่ฉันทำ

ใช้manage.py reset southเป็นไม่ได้เป็นความคิดที่ดีหากคุณมีปพลิเคชันของบุคคลที่สามที่ใช้ใต้ยกตัวอย่างเช่นdjango-cms (ทุกอย่างโดยทั่วไปใช้ใต้)

reset south จะลบประวัติการย้ายข้อมูลทั้งหมดสำหรับแอพทั้งหมดที่คุณติดตั้ง

ตอนนี้พิจารณาว่าคุณอัพเกรดเป็นเวอร์ชั่นล่าสุดก็จะมีการโยกย้ายใหม่เช่นdjango-cms 0009_do_something.pyภาคใต้จะสับสนเมื่อคุณพยายามเรียกใช้การโยกย้ายนั้นโดยไม่ต้อง0001ผ่าน0008ประวัติการโยกย้าย

จะดีกว่า / ปลอดภัยกว่ามากในการเลือกเฉพาะแอพที่คุณดูแลเท่านั้น


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

1. ลบประวัติการย้ายข้อมูลสำหรับแอพของฉัน

sql> delete from south_migrationhistory where app_name = 'my_app';

2. ลบการย้ายข้อมูลสำหรับแอพของฉัน

$ rm -rf my_app/migrations/

3. สร้างการโยกย้ายครั้งแรกใหม่สำหรับแอพของฉัน

$ ./manage.py schemamigration --initial my_app

4. ปลอมทำการโยกย้ายครั้งแรกสำหรับแอพของฉัน

สิ่งนี้จะแทรกการย้ายเข้าไปsouth_migrationhistoryโดยไม่ต้องสัมผัสตารางจริง:

$ ./manage.py migrate --fake my_app

จริง ๆ แล้วขั้นตอนที่ 3 และ 4 เป็นเพียงความแตกต่างที่ยาวกว่าmanage.py convert_to_south my_appแต่ฉันต้องการการควบคุมพิเศษในสถานการณ์ที่ละเอียดอ่อนเช่นการปรับเปลี่ยนฐานข้อมูลการผลิต


2
ฉันแก้ไขคำตอบของฉันเพื่อรวมการแก้ไขปัญหาที่คุณพบ (เพียงเดาตามคำตอบของคุณ) และทดสอบในฐานข้อมูลการผลิตที่มีหลายล้านแถว
เตาแก๊ส

2
นี่คือสิ่งที่เรากำลังทำอยู่ หากคุณใช้ตัวเลือก - ลบ-ghost-migrations ในขั้นตอนที่ 4 คุณสามารถออกจากขั้นตอนที่ 1 ได้
tobych

คุณควรระบุชื่อแอพอย่างชัดเจน./manage.py migrate --fakeหากคุณไม่ต้องการทำการโยกย้ายแอพอื่น ๆ ที่มีการย้ายที่ค้างอยู่
wadim

2
@wadim ดังนั้นขั้นตอนที่ 0: "ตรวจสอบให้แน่ใจว่าคุณไม่มี desync ระหว่างการย้ายข้อมูลบนดิสก์และการย้ายข้อมูลที่ดำเนินการบนฐานข้อมูล"
thnee

@thnee อาจกล่าวได้ว่าคุณกำลังอ้างถึงแอพที่ติดตั้งไว้ทั้งหมดในขั้นตอนที่ 0 คุณรู้วิธีที่ง่ายในการทำขั้นตอนที่ 0 หรือไม่?
wadim

7

เช่นเดียวกับ thnee (ดูคำตอบของเธอ) เรากำลังใช้วิธีการที่นุ่มนวลกับคำแนะนำของผู้เขียนใต้ (Andrew Godwin) ที่อ้างถึงที่อื่นที่นี่และเราแยกสิ่งที่เราทำกับฐานรหัสจากสิ่งที่เราทำกับฐานข้อมูลระหว่างการปรับใช้ เนื่องจากเราต้องการการปรับใช้เพื่อให้สามารถทำซ้ำได้:

เราทำอะไรในรหัส:

# Remove all the migrations from the app
$ rm -fR appname/migrations
# Make the first migration (don't touch the database)
$ ./manage.py schemamigration appname --initial

สิ่งที่เราทำกับฐานข้อมูลเมื่อมีการปรับใช้รหัสนั้น

# Fake the migration history, wiping out the rest
$ ./manage.py migrate appname --fake --delete-ghost-migrations

ฉันคิดว่าฉันทำสิ่งเดียวกัน แต่ลบรายการฐานข้อมูลด้วยตนเองแทนที่จะใช้ --delete_ghoist-migrations วิธีการของคุณดีกว่านิดหน่อย
wobbily_col

1

หากคุณเพียงแค่ทำงานกับเครื่อง dev ฉันเขียนคำสั่งการจัดการที่ทำตามที่ Dominique แนะนำ

http://balzerg.blogspot.co.il/2012/09/django-app-reset-with-south.html

ตรงกันข้ามกับข้อเสนอแนะของผู้แต่งทางทิศใต้สิ่งนี้จะไม่เป็นอันตรายแอพอื่น ๆ ที่ติดตั้งโดยใช้ทิศใต้


และหากคุณต้องการเก็บการย้ายข้อมูลที่มีอยู่เดิม (เช่นคุณต้องการรีเซ็ตแอปรวมถึงประวัติการย้ายข้อมูล แต่เก็บการย้ายข้อมูลจริงไว้) คุณสามารถลองทำสิ่งนี้ได้: goo.gl/0ZnWm
mgalgs

1

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

เป็นครั้งแรก:

(1) find . -type d -name migrations -exec git rm -rf '{}' \;
(2) find . -type d -name migrations -exec rm -rf '{}' \;
(3) ./manage.py schemamigration <APP_NAME> --initial
(4) [GIT COMMIT]

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

(5) [GIT PULL]
(6) ./manage.py reset south
(7) ./manage.py migrate --fake

ทำเริ่มต้น (3) สำหรับแต่ละแอพที่คุณต้องการกลับมามีส่วนร่วมอีกครั้ง โปรดทราบว่าการรีเซ็ต (6) จะลบเฉพาะประวัติการย้ายข้อมูลจึงไม่เป็นอันตรายต่อไลบรารี การย้ายถิ่นปลอม (7) จะลบประวัติการย้ายข้อมูลของแอปของบุคคลที่สามที่ติดตั้ง


0

ลบไฟล์ที่จำเป็นออกจากโฟลเดอร์แอพ

เส้นทางตัวอย่าง

 cd /usr/local/lib/python2.7/dist-packages/wiki/south_migrations

วิกิ - เป็นแอพของฉัน

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