首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >重命名模型和关系字段的Django迁移策略

问重命名模型和关系字段的Django迁移策略
EN

Stack Overflow用户
提问于 2014-08-02 02:37:22
回答 13查看 118.9K关注 0票数 197

我计划在一个已有的Django项目中重命名几个模型,其中有许多与我想重命名的模型有外键关系的模型。我相当肯定这将需要多次迁移,但我不确定确切的步骤。

假设我从名为myapp的Django应用程序中的以下模型开始

代码语言:javascript
复制
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开发文档中所读到的,我假设以下迁移策略:

第一步

修改models.py

代码语言:javascript
复制
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,我将有可能丢失该列中的数据。

第二步

创建一个空迁移:

代码语言:javascript
复制
python manage.py makemigrations --empty myapp

第三步

编辑步骤2中创建的迁移文件中的Migration类,将RenameModel操作添加到操作列表中:

代码语言:javascript
复制
class Migration(migrations.Migration):

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

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

第四步

应用迁移:

代码语言:javascript
复制
python manage.py migrate

第五步

在models.py中编辑相关字段名

代码语言:javascript
复制
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()

第六步

创建另一个空迁移:

代码语言:javascript
复制
python manage.py makemigrations --empty myapp

第7步

在步骤6中创建的迁移文件中编辑Migration类,以便将任何相关字段名的RenameField操作添加到操作列表中:

代码语言:javascript
复制
class Migration(migrations.Migration):

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

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

步骤8

适用第二次迁移:

代码语言:javascript
复制
python manage.py migrate

除了更新代码的其余部分(视图、表单等)为了反映新的变量名,新的迁移功能基本上是这样工作的吗?

而且,这似乎是很多步骤。迁移操作能在某种程度上压缩吗?

谢谢!

EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2014-10-07 17:22:03

因此,当我尝试这个时,似乎可以压缩步骤3-7:

代码语言:javascript
复制
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和更旧的迁移文件(!),可能会出现一些错误。

更新:正如杜巴罗提到的,较新版本的杜巴罗通常能够检测并询问模型是否被重命名。所以,首先尝试manage.py makemigrations,然后检查迁移文件。

票数 169
EN

Stack Overflow用户

发布于 2015-06-03 13:21:19

起初,我认为Fiver的方法适用于我,因为在第4步之前迁移很好。但是,将'ForeignKeyField(Foo)‘隐式更改为'ForeignKeyField(Bar)’在任何迁移中都没有关联。这就是为什么当我想重命名关系字段时迁移失败的原因(步骤5-8)。这可能是因为我的“AnotherModel”和“YetAnotherModel”在其他应用程序中被分派给我。

因此,我按照以下步骤重命名了我的模型和关系字段:

我采用了这的方法,特别是奥特兰策的技巧。

就像我们在,myapp,

代码语言:javascript
复制
class Foo(models.Model):
    name = models.CharField(unique=True, max_length=32)
    description = models.TextField(null=True, blank=True)

在肌疗法中,

代码语言:javascript
复制
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()。(这将将关联Foo对象的id保留为整数字段的值)。

代码语言:javascript
复制
class AnotherModel(models.Model):
    foo = models.IntegerField()
    is_awesome = models.BooleanField()

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

然后

代码语言:javascript
复制
python manage.py makemigrations

python manage.py migrate

步骤2:(类似于Fiver的第2-4步)

更改模型名称

代码语言:javascript
复制
class Bar(models.Model):  # <-- changed model name
    name = models.CharField(unique=True, max_length=32)
    description = models.TextField(null=True, blank=True)

创建一个空迁移:

代码语言:javascript
复制
python manage.py makemigrations --empty myapp

然后编辑如下:

代码语言:javascript
复制
class Migration(migrations.Migration):

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

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

最终

代码语言:javascript
复制
python manage.py migrate

步骤3:

将IntegerField()转换回以前的ForeignKeyField或OneToOneField,但使用新的条形模型。(前一个整域正在存储id,因此django理解这一点,并重新建立连接,这是很酷的。)

代码语言:javascript
复制
class AnotherModel(models.Model):
    foo = models.ForeignKey(Bar)
    is_awesome = models.BooleanField()

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

那就做:

代码语言:javascript
复制
python manage.py makemigrations 

非常重要,在这一步中,您必须修改每个新迁移并添加对RenameModel Foo-> Bar迁移的依赖项。因此,如果AnotherModel和YetAnotherModel都在肌治疗中,则肌治疗中创建的迁移必须如下所示:

代码语言:javascript
复制
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')
        ),
    ]

然后

代码语言:javascript
复制
python manage.py migrate

步骤4:

最终您可以重命名您的字段。

代码语言:javascript
复制
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()

然后进行自动重命名

代码语言:javascript
复制
python manage.py makemigrations

(django应该问您是否真的重命名了模型名,请说是)

代码语言:javascript
复制
python manage.py migrate

就这样!

这适用于Django1.8

票数 46
EN

Stack Overflow用户

发布于 2020-12-10 15:09:20

在当前版本的Django中,您可以重命名模型并运行python manage.py makemigrations,然后django将询问您是否要重命名模型,如果您选择是,那么所有重命名过程都将自动完成。

票数 26
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25091130

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档