กลยุทธ์การย้ายข้อมูล Django สำหรับการเปลี่ยนชื่อโมเดลและฟิลด์ความสัมพันธ์


153

ฉันวางแผนที่จะเปลี่ยนชื่อรุ่นหลายรุ่นในโครงการ Django ที่มีอยู่ซึ่งมีโมเดลอื่น ๆ อีกมากมายที่มีความสัมพันธ์กับกุญแจต่างประเทศเป็นแบบที่ฉันต้องการเปลี่ยนชื่อ ฉันค่อนข้างแน่ใจว่าจะต้องมีการย้ายหลายครั้ง แต่ฉันไม่แน่ใจเกี่ยวกับขั้นตอนที่แน่นอน

สมมติว่าฉันเริ่มด้วยโมเดลต่อไปนี้ภายในแอป Django ที่เรียกว่าmyapp:

class Foo(models.Model):
    name = models.CharField(unique=True, max_length=32)
    description = models.TextField(null=True, blank=True)


class AnotherModel(models.Model):
    foo = models.ForeignKey(Foo)
    is_awesome = models.BooleanField()


class YetAnotherModel(models.Model):
    foo = models.ForeignKey(Foo)
    is_ridonkulous = models.BooleanField()

ฉันต้องการเปลี่ยนชื่อFooรุ่นเพราะชื่อไม่สมเหตุสมผลและทำให้เกิดความสับสนในรหัสและBarจะทำให้ชื่อชัดเจนขึ้น

จากสิ่งที่ฉันได้อ่านในเอกสารการพัฒนาของ Django ฉันคิดว่ากลยุทธ์การย้ายข้อมูลต่อไปนี้:

ขั้นตอนที่ 1

แก้ไขmodels.py:

class Bar(models.Model):  # <-- changed model name
    name = models.CharField(unique=True, max_length=32)
    description = models.TextField(null=True, blank=True)


class AnotherModel(models.Model):
    foo = models.ForeignKey(Bar)  # <-- changed relation, but not field name
    is_awesome = models.BooleanField()


class YetAnotherModel(models.Model):
    foo = models.ForeignKey(Bar)  # <-- changed relation, but not field name
    is_ridonkulous = models.BooleanField()

โปรดสังเกตว่าAnotherModelชื่อเขตข้อมูลสำหรับfooจะไม่เปลี่ยนแปลง แต่ความสัมพันธ์จะอัปเดตเป็นBarรูปแบบ เหตุผลของฉันคือฉันไม่ควรเปลี่ยนมากเกินไปในครั้งเดียวและถ้าฉันเปลี่ยนชื่อฟิลด์นี้เป็นbarฉันจะเสี่ยงสูญเสียข้อมูลในคอลัมน์นั้น

ขั้นตอนที่ 2

สร้างการโยกย้ายที่ว่างเปล่า:

python manage.py makemigrations --empty myapp

ขั้นตอนที่ 3

แก้ไขMigrationคลาสในไฟล์การโอนย้ายที่สร้างในขั้นตอนที่ 2 เพื่อเพิ่มการRenameModelดำเนินการไปยังรายการการดำเนินการ:

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0001_initial'),
    ]

    operations = [
        migrations.RenameModel('Foo', 'Bar')
    ]

ขั้นตอนที่ 4

ใช้การโยกย้าย:

python manage.py migrate

ขั้นตอนที่ 5

แก้ไขชื่อฟิลด์ที่เกี่ยวข้องในmodels.py:

class Bar(models.Model):
    name = models.CharField(unique=True, max_length=32)
    description = models.TextField(null=True, blank=True)


class AnotherModel(models.Model):
    bar = models.ForeignKey(Bar)  # <-- changed field name
    is_awesome = models.BooleanField()


class YetAnotherModel(models.Model):
    bar = models.ForeignKey(Bar)  # <-- changed field name
    is_ridonkulous = models.BooleanField()

ขั้นตอนที่ 6

สร้างการโยกย้ายที่ว่างเปล่าอื่น:

python manage.py makemigrations --empty myapp

ขั้นตอนที่ 7

แก้ไขMigrationคลาสในไฟล์การโอนย้ายที่สร้างในขั้นตอนที่ 6 เพื่อเพิ่มการRenameFieldดำเนินการสำหรับชื่อฟิลด์ที่เกี่ยวข้องในรายการการดำเนินการ:

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0002_rename_fields'),  # <-- is this okay?
    ]

    operations = [
        migrations.RenameField('AnotherModel', 'foo', 'bar'),
        migrations.RenameField('YetAnotherModel', 'foo', 'bar')
    ]

ขั้นตอนที่ 8

ใช้การโยกย้ายครั้งที่ 2:

python manage.py migrate

นอกเหนือจากการอัปเดตโค้ดส่วนที่เหลือ (มุมมองฟอร์มและอื่น ๆ ) เพื่อให้สะท้อนถึงชื่อตัวแปรใหม่แล้วนี่คือการทำงานของการย้ายข้อมูลใหม่หรือไม่

นอกจากนี้ดูเหมือนว่าขั้นตอนมากมาย การดำเนินการโยกย้ายสามารถย่อตัวได้หรือไม่?

ขอบคุณ!

คำตอบ:


127

ดังนั้นเมื่อฉันลองทำสิ่งนี้ดูเหมือนว่าคุณสามารถย่อขั้นตอนที่ 3 - 7:

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0001_initial'), 
    ]

    operations = [
        migrations.RenameModel('Foo', 'Bar'),
        migrations.RenameField('AnotherModel', 'foo', 'bar'),
        migrations.RenameField('YetAnotherModel', 'foo', 'bar')
    ]

คุณอาจได้รับข้อผิดพลาดบางอย่างหากคุณไม่อัปเดตชื่อที่นำเข้าเช่น admin.py และแม้แต่ไฟล์การโยกย้ายที่เก่ากว่า (!)

ปรับปรุง : เป็นceasaroกล่าวถึงรุ่นใหม่ของ Django มักจะสามารถตรวจสอบและถามว่ารูปแบบที่มีการเปลี่ยนชื่อ ดังนั้นmanage.py makemigrationsก่อนอื่นให้ตรวจสอบไฟล์การโยกย้าย


ขอบคุณสำหรับคำตอบ. ฉันได้ทำการโยกย้ายโดยใช้ขั้นตอนที่ระบุไว้ แต่ฉันอยากรู้ว่าคุณลองทำกับข้อมูลที่มีอยู่หรือเพียงแค่ใช้ฐานข้อมูลเปล่า?
Fiver

2
พยายามกับข้อมูลที่มีอยู่แม้ว่าจะมีเพียงไม่กี่แถวบน sqlite ใน env ท้องถิ่นของฉัน (เมื่อฉันย้ายไปยังการผลิตฉันตั้งใจจะล้างทุกอย่างออกรวมถึงไฟล์การโยกย้าย)
wasabigeek

4
คุณไม่จำเป็นต้องเปลี่ยนชื่อรุ่นในไฟล์การโยกย้ายหากใช้apps.get_modelในนั้น ฉันใช้เวลามากในการคิดออก
ahmed

9
ใน django 2.0 หากคุณเปลี่ยนชื่อรุ่น./manage.py makemigrations myappคำสั่งจะถามคุณว่าคุณเปลี่ยนชื่อรุ่นของคุณหรือไม่ เช่นคุณเปลี่ยนชื่อ myapp.Foo เป็น Bar หรือไม่ [y / N]หากคุณตอบ'y' การย้ายข้อมูลของคุณจะมีmigration.RenameModel('Foo', 'Bar')จำนวนเหมือนกันสำหรับฟิลด์ที่เปลี่ยนชื่อ :-)
ceasaro

1
manage.py makemigrations myappอาจยังล้มเหลว: "คุณอาจต้องเพิ่มสิ่งนี้ด้วยตนเองหากคุณเปลี่ยนชื่อรุ่นและฟิลด์บางส่วนในครั้งเดียวไปที่ตัวตรวจจับอัตโนมัตินี่จะดูเหมือนว่าคุณลบแบบจำลองด้วยชื่อเก่าและเพิ่มชื่อใหม่ด้วย ชื่ออื่นและการย้ายข้อมูลที่สร้างจะสูญเสียข้อมูลใด ๆ ในตารางเก่า " Django 2.1 เอกสาร สำหรับฉันมันก็เพียงพอแล้วที่จะสร้างการย้ายข้อมูลที่ว่างเปล่าเพิ่มรูปแบบการเปลี่ยนชื่อไปยังมันแล้วเรียกใช้makemigrationsตามปกติ
15159

37

ในตอนแรกฉันคิดว่าวิธีการของ Fiver ใช้งานได้ดีเพราะการโยกย้ายทำงานได้ดีจนถึงขั้นตอนที่ 4 อย่างไรก็ตามการเปลี่ยนแปลงโดยนัย 'ForeignKeyField (Foo)' เป็น 'ForeignKeyField (Bar)' ไม่เกี่ยวข้องกับการโยกย้ายใด ๆ นี่คือสาเหตุที่การโยกย้ายล้มเหลวเมื่อฉันต้องการเปลี่ยนชื่อเขตข้อมูลความสัมพันธ์ (ขั้นตอนที่ 5-8) นี่อาจเป็นเพราะความจริงที่ว่า 'AnotherModel' และ 'YetAnotherModel' ของฉันได้รับการจัดส่งในแอพอื่นในกรณีของฉัน

ดังนั้นฉันจึงเปลี่ยนชื่อรุ่นและเขตข้อมูลความสัมพันธ์โดยทำตามขั้นตอนด้านล่าง:

ฉันปรับวิธีการจากสิ่งนี้และโดยเฉพาะอย่างยิ่งเคล็ดลับของ otranzer

เช่นเดียวกับ Fiver สมมติว่าเรามีในmyapp :

class Foo(models.Model):
    name = models.CharField(unique=True, max_length=32)
    description = models.TextField(null=True, blank=True)

และในmyotherapp :

class AnotherModel(models.Model):
    foo = models.ForeignKey(Foo)
    is_awesome = models.BooleanField()


class YetAnotherModel(models.Model):
    foo = models.ForeignKey(Foo)
    is_ridonkulous = models.BooleanField()

ขั้นตอนที่ 1:

แปลงทุก OneToOneField (Foo) หรือ ForeignKeyField (Foo) เป็น IntegerField () (สิ่งนี้จะเก็บ id ของวัตถุ Foo ที่เกี่ยวข้องเป็นค่าของจำนวนเต็ม)

class AnotherModel(models.Model):
    foo = models.IntegerField()
    is_awesome = models.BooleanField()

class YetAnotherModel(models.Model):
    foo = models.IntegerField()
    is_ridonkulous = models.BooleanField()

แล้วก็

python manage.py makemigrations

python manage.py migrate

ขั้นตอนที่ 2: (เช่นเดียวกับขั้นตอน 2-4 จาก Fiver)

เปลี่ยนชื่อรุ่น

class Bar(models.Model):  # <-- changed model name
    name = models.CharField(unique=True, max_length=32)
    description = models.TextField(null=True, blank=True)

สร้างการโยกย้ายที่ว่างเปล่า:

python manage.py makemigrations --empty myapp

จากนั้นแก้ไขเช่น:

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0001_initial'),
    ]

    operations = [
        migrations.RenameModel('Foo', 'Bar')
    ]

ในที่สุด

python manage.py migrate

ขั้นตอนที่ 3:

แปลงกลับ IntegerField ของคุณ () เป็น ForeignKeyField หรือ OneToOneField ก่อนหน้าของพวกเขา แต่ด้วย Bar Model ใหม่ (จำนวนเต็มก่อนหน้านี้ถูกจัดเก็บ id ดังนั้น django จึงเข้าใจและสถาปนาการเชื่อมต่อใหม่ซึ่งยอดเยี่ยม)

class AnotherModel(models.Model):
    foo = models.ForeignKey(Bar)
    is_awesome = models.BooleanField()

class YetAnotherModel(models.Model):
    foo = models.ForeignKey(Bar)
    is_ridonkulous = models.BooleanField()

จากนั้นทำ:

python manage.py makemigrations 

ที่สำคัญอย่างยิ่งในขั้นตอนนี้คุณต้องแก้ไขการโยกย้ายใหม่ทุกครั้งและเพิ่มการพึ่งพา RenameModel Foo-> การโอนย้ายแถบ ดังนั้นหาก AnotherModel และ YetAnotherModel อยู่ใน myotherapp การโยกย้ายที่สร้างขึ้นใน myotherapp จะต้องมีลักษณะเช่นนี้:

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '00XX_the_migration_of_myapp_with_renamemodel_foo_bar'),
        ('myotherapp', '00xx_the_migration_of_myotherapp_with_integerfield'),
    ]

    operations = [
        migrations.AlterField(
            model_name='anothermodel',
            name='foo',
            field=models.ForeignKey(to='myapp.Bar'),
        ),
        migrations.AlterField(
            model_name='yetanothermodel',
            name='foo',
            field=models.ForeignKey(to='myapp.Bar')
        ),
    ]

แล้วก็

python manage.py migrate

ขั้นตอนที่ 4:

ในที่สุดคุณสามารถเปลี่ยนชื่อสาขาของคุณ

class AnotherModel(models.Model):
    bar = models.ForeignKey(Bar) <------- Renamed fields
    is_awesome = models.BooleanField()


class YetAnotherModel(models.Model):
    bar = models.ForeignKey(Bar) <------- Renamed fields
    is_ridonkulous = models.BooleanField()

จากนั้นทำการเปลี่ยนชื่ออัตโนมัติ

python manage.py makemigrations

(django ควรถามคุณว่าคุณเปลี่ยนชื่อ modelname จริงหรือไม่ตอบว่าใช่)

python manage.py migrate

และนั่นมัน!

ใช้งานได้กับ Django1.8


3
ขอบคุณ! นั่นเป็นประโยชน์อย่างมาก แต่หมายเหตุ - ฉันต้องเปลี่ยนชื่อและ / หรือลบดัชนีฟิลด์ PostgreSQL ด้วยมือเพราะหลังจากเปลี่ยนชื่อ Foo เป็น Bar ฉันได้สร้างโมเดลใหม่ชื่อ Bar
Anatoly Scherbakov

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

ขอบคุณ! ฉันลองใช้กลยุทธ์ที่แตกต่างกันมากมายเพื่อเปลี่ยนชื่อรุ่นที่รุ่นอื่นมีกุญแจต่างประเทศเป็น (ขั้นตอนที่ 1-3) และนี่เป็นเพียงวิธีเดียวที่ทำงานได้
MSH

การเปลี่ยนForeignKeyเป็นIntegerFieldบันทึกวันของฉันวันนี้!
เมห์เม็ต

8

ฉันต้องการทำสิ่งเดียวกันและติดตาม ฉันเปลี่ยนโมเดลทั้งหมดในคราวเดียว (ขั้นตอนที่ 1 และ 5 พร้อมกันจากคำตอบของ Fiver) จากนั้นสร้างการย้ายสคีมา แต่แก้ไขเป็น:

class Migration(SchemaMigration):
    def forwards(self, orm):
        db.rename_table('Foo','Bar')

    def backwards(self, orm):
        db.rename_table('Bar','Foo')

มันทำงานได้อย่างสมบูรณ์แบบ ข้อมูลที่มีอยู่ทั้งหมดของฉันปรากฏขึ้นตารางอื่น ๆ ทั้งหมดที่อ้างอิงแถบปรับ

จากที่นี่: https://hanmir.wordpress.com/2012/08/30/rename-model-django-south-migration/


เยี่ยมมากขอบคุณสำหรับการแบ่งปัน อย่าลืม +1 wasibigeek ถ้าคำตอบนั้นช่วยได้
Fiver

7

สำหรับ Django 1.10 ฉันสามารถเปลี่ยนชื่อคลาสโมเดลได้สองชื่อ (รวมถึง ForeignKey และ data) เพียงแค่เรียกใช้ Makemigrations จากนั้นโอนย้ายแอป สำหรับขั้นตอน Makemigrations ฉันต้องยืนยันว่าฉันต้องการเปลี่ยนชื่อตาราง การโยกย้ายเปลี่ยนชื่อของตารางโดยไม่มีปัญหา

จากนั้นฉันเปลี่ยนชื่อของฟิลด์ ForeignKey ให้ตรงกันและ Makemigrations ถูกถามอีกครั้งเพื่อยืนยันว่าฉันต้องการเปลี่ยนชื่อ โยกย้ายเกินกว่าที่จะทำการเปลี่ยนแปลง

ดังนั้นฉันจึงดำเนินการสองขั้นตอนโดยไม่มีการแก้ไขไฟล์พิเศษใด ๆ ฉันได้รับข้อผิดพลาดในตอนแรกเพราะฉันลืมเปลี่ยนไฟล์ admin.py ดังที่ @wasibigeek พูดถึง


ขอบคุณมาก! สมบูรณ์แบบสำหรับ Django 1.11 เช่นกัน
ฟรานซิสโก

6

ฉันยังประสบปัญหาตามที่ v.thorey อธิบายและพบว่าวิธีการของเขามีประโยชน์มาก แต่สามารถย่อเป็นขั้นตอนน้อยลงซึ่งจริง ๆ แล้วขั้นตอนที่ 5 ถึง 8 เป็น Fiver อธิบายโดยไม่ต้องขั้นตอนที่ 1 ถึง 4 ยกเว้นขั้นตอนที่ 7 ต้องเปลี่ยนตามฉัน ด้านล่างขั้นตอนที่ 3 ขั้นตอนโดยรวมมีดังนี้:

ขั้นตอนที่ 1: แก้ไขชื่อฟิลด์ที่เกี่ยวข้องใน models.py

class Bar(models.Model):
    name = models.CharField(unique=True, max_length=32)
    description = models.TextField(null=True, blank=True)


class AnotherModel(models.Model):
    bar = models.ForeignKey(Bar)  # <-- changed field name
    is_awesome = models.BooleanField()


class YetAnotherModel(models.Model):
    bar = models.ForeignKey(Bar)  # <-- changed field name
    is_ridonkulous = models.BooleanField()

ขั้นตอนที่ 2: สร้างการโยกย้ายที่ว่างเปล่า

python manage.py makemigrations --empty myapp

ขั้นตอนที่ 3: แก้ไขคลาสการย้ายข้อมูลในไฟล์การโยกย้ายที่สร้างในขั้นตอนที่ 2

class Migration(migrations.Migration):

dependencies = [
    ('myapp', '0001_initial'), 
]

operations = [
    migrations.AlterField(
        model_name='AnotherModel',
        name='foo',
        field=models.IntegerField(),
    ),
    migrations.AlterField(
        model_name='YetAnotherModel',
        name='foo',
        field=models.IntegerField(),
    ),
    migrations.RenameModel('Foo', 'Bar'),
    migrations.AlterField(
        model_name='AnotherModel',
        name='foo',
        field=models.ForeignKey(to='myapp.Bar'),
    ),
    migrations.AlterField(
        model_name='YetAnotherModel',
        name='foo',
        field=models.ForeignKey(to='myapp.Bar'),
    ),
    migrations.RenameField('AnotherModel', 'foo', 'bar'),
    migrations.RenameField('YetAnotherModel', 'foo', 'bar')
]

ขั้นตอนที่ 4: ใช้การโยกย้าย

python manage.py migrate

เสร็จสิ้น

PS ฉันได้ลองวิธีนี้บน Django 1.9 แล้ว


5

ฉันใช้ Django เวอร์ชั่น 1.9.4

ฉันได้ทำตามขั้นตอนต่อไปนี้: -

ฉันได้เพียงแค่เปลี่ยนชื่อรุ่น oldname เพื่อ NewName python manage.py makemigrationsRun มันจะขอให้คุณ Did you rename the appname.oldName model to NewName? [y/N]เลือก Y

เรียกใช้python manage.py migrateและมันจะขอให้คุณ

ประเภทเนื้อหาต่อไปนี้เก่าและจำเป็นต้องลบ:

appname | oldName
appname | NewName

วัตถุใด ๆ ที่เกี่ยวข้องกับประเภทเนื้อหาเหล่านี้โดย foreign key จะถูกลบด้วย คุณแน่ใจหรือว่าต้องการลบประเภทเนื้อหาเหล่านี้ หากคุณไม่แน่ใจให้ตอบ 'ไม่'

Type 'yes' to continue, or 'no' to cancel: Select No

เปลี่ยนชื่อและย้ายข้อมูลที่มีอยู่ทั้งหมดไปยังตารางที่ระบุชื่อใหม่สำหรับฉัน


ขอบคุณเพื่อนฉันสับสนเพราะไม่มีอะไรเกิดขึ้นเมื่อหลังจากกดปุ่ม "ไม่"
farhawa

3

น่าเสียดายที่ฉันพบปัญหา (แต่ละ django 1.x) ด้วยการเปลี่ยนชื่อการโยกย้ายซึ่งออกจากชื่อตารางเก่าในฐานข้อมูล

Django ไม่ได้ลองอะไรบนโต๊ะเก่าแค่เปลี่ยนชื่อรุ่นของเขาเอง ปัญหาเดียวกันกับกุญแจต่างประเทศและดัชนีโดยทั่วไป - การเปลี่ยนแปลงมีการติดตามที่ Django ไม่ถูกต้อง

โซลูชันที่ง่ายที่สุด (วิธีแก้ปัญหา):

class Foo(models.Model):
     name = models.CharField(unique=True, max_length=32)
     ...
Bar = Foo  # and use Bar only

ทางออกที่แท้จริง (วิธีง่ายๆในการสลับดัชนีข้อ จำกัด ทริกเกอร์ชื่อ ฯลฯ ทั้งหมดใน 2 คอมมิท แต่เป็นตารางที่เล็กกว่า ):

กระทำ A:

  1. สร้างโมเดลเดียวกันกับโมเดลเก่า
# deprecated - TODO: TO BE REMOVED
class Foo(model.Model):
    ...

class Bar(model.Model):
    ...
  1. เปลี่ยนรหัสเพื่อทำงานกับรุ่นใหม่Barเท่านั้น (รวมถึงความสัมพันธ์ทั้งหมดในสคีมา)

ในการเตรียมการย้ายข้อมูลRunPythonซึ่งคัดลอกข้อมูลจาก Foo ไปที่ Bar (รวมถึงidFoo)

  1. การเพิ่มประสิทธิภาพที่ไม่จำเป็น (ถ้าจำเป็นสำหรับตารางที่มากขึ้น)

ส่ง B: (ไม่ต้องรีบทำเมื่อย้ายทีมทั้งหมด)

  1. ดร็อปรุ่นเก่าอย่างปลอดภัย Foo

ล้างข้อมูลเพิ่มเติม:

  • สควอชในการโยกย้าย

ข้อผิดพลาดใน Django:


3

แค่อยากจะยืนยันและเพิ่มความคิดเห็น ceasaro Django 2.0 ดูเหมือนว่าจะทำสิ่งนี้โดยอัตโนมัติในขณะนี้

ฉันใช้ Django 2.2.1 แล้วฉันต้องทำอะไรเพื่อเปลี่ยนชื่อรุ่นและเรียกใช้ makemigrationsสิ่งที่ผมต้องทำในสิ่งที่จะเปลี่ยนชื่อรุ่นและวิ่ง

ที่นี่มันถามว่าฉันได้เปลี่ยนชื่อชั้นเฉพาะจากAเป็นBฉันเลือกใช่และวิ่งโยกย้ายและดูเหมือนว่าจะทำงานทั้งหมด

หมายเหตุฉันไม่ได้เปลี่ยนชื่อชื่อรุ่นเก่าในไฟล์ใด ๆ ภายในโฟลเดอร์โครงการ / การย้ายข้อมูล


1

ฉันต้องการเปลี่ยนชื่อโต๊ะสองสามโต๊ะ แต่การเปลี่ยนชื่อโมเดลเพียงอันเดียวก็ถูกสังเกตเห็นโดย Django นั่นเกิดขึ้นเพราะ Django วนซ้ำมากกว่ารุ่นที่ออกแล้ว สำหรับแต่ละคู่มันจะตรวจสอบว่าเป็นแอพเดียวกันและมีฟิลด์เหมือนกันหรือไม่หรือไม่ มีเพียงตารางเดียวเท่านั้นที่ไม่มีคีย์ต่างประเทศในตารางที่จะเปลี่ยนชื่อ (คีย์ต่างประเทศมีชื่อคลาสโมเดลตามที่คุณจำได้) กล่าวอีกนัยหนึ่งเพียงหนึ่งตารางไม่มีการเปลี่ยนแปลงฟิลด์ นั่นเป็นเหตุผลที่มันถูกสังเกตเห็น

ดังนั้นวิธีแก้ไขคือเปลี่ยนชื่อโต๊ะหนึ่งครั้งเปลี่ยนชื่อคลาสโมเดลmodels.pyเป็นไปviews.pyได้และทำการโอนย้าย หลังจากนั้นตรวจสอบรหัสของคุณสำหรับการอ้างอิงอื่น ๆ (ชื่อคลาสโมเดลชื่อที่เกี่ยวข้อง (แบบสอบถาม) ชื่อตัวแปร) ทำการโยกย้ายหากจำเป็น จากนั้นเลือกที่จะรวมการย้ายข้อมูลทั้งหมดเหล่านี้ไว้ในที่เดียว (ตรวจสอบให้แน่ใจว่าได้คัดลอกการนำเข้าด้วย)


1

ฉันจะทำให้ @ceasaro คำพูดของฉันในความคิดเห็นของเขาในคำตอบนี้

Django เวอร์ชันใหม่สามารถตรวจจับการเปลี่ยนแปลงและถามเกี่ยวกับสิ่งที่ทำ ฉันยังจะเพิ่มที่ Django อาจผสมลำดับของการดำเนินการของคำสั่งโยกย้ายบางคำสั่ง

มันจะฉลาดที่จะใช้การเปลี่ยนแปลงเล็ก ๆ และเรียกใช้makemigrationsและmigrateและหากเกิดข้อผิดพลาดไฟล์โยกย้ายสามารถแก้ไขได้

ลำดับการดำเนินการบางบรรทัดสามารถเปลี่ยนแปลงได้เพื่อหลีกเลี่ยงข้อผิดพลาด


ที่ดีที่จะทราบว่านี้ไม่ได้ทำงานถ้าคุณเปลี่ยนชื่อรุ่นและมีปุ่มต่างประเทศที่กำหนดไว้ ฯลฯ ...
คณบดี Kayton

การขยายความคิดเห็นก่อนหน้า: ถ้าฉันทำทั้งหมดคือเปลี่ยนชื่อรุ่นและเรียกใช้ makemigrations ฉันได้รับ 'NameError: ชื่อ' <oldmodel> 'ไม่ได้กำหนดไว้' ใน foreignkeys ฯลฯ ... ถ้าฉันเปลี่ยนและเรียกใช้ makemigrations ฉันได้รับข้อผิดพลาดในการนำเข้า ใน admin.py ... ถ้าฉันแก้ไขและเรียกใช้ makemigrations อีกครั้งฉันได้รับพรอมต์ 'คุณเปลี่ยนชื่อโมเดล <app.oldmodel> เป็น <newmodel>' แต่จากนั้นในการใช้การย้ายข้อมูลฉันได้รับ 'ValueError: ฟิลด์ <app .newmodel.field1> ถูกประกาศโดยมีการอ้างอิงขี้เกียจไปที่ '<app.oldmodel>' แต่แอป '<app>' ไม่ได้ให้รูปแบบ '<oldmodel>' ฯลฯ ... '
Dean Kayton

ข้อผิดพลาดนี้ดูเหมือนว่าคุณต้องเปลี่ยนชื่อการอ้างอิงในการย้ายข้อมูลประวัติของคุณ
mhatch

@DeanKayton จะบอกว่าmigrations.SeparateDatabaseAndStateสามารถช่วยได้อย่างไร
diogosimao

1

หากคุณใช้ IDE ที่ดีอย่าง PyCharm คุณสามารถคลิกขวาที่ชื่อรุ่นและทำการเปลี่ยนชื่อ -> เปลี่ยนชื่อ สิ่งนี้จะช่วยให้คุณไม่ต้องกังวลกับรหัสทั้งหมดที่อ้างถึงโมเดล จากนั้นเรียกใช้ makemigrations และโอนย้าย Django 2+ จะยืนยันการเปลี่ยนชื่อ


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