Django南:在数据迁移中改变字段类型 [英] Django south: changing field type in data migration

查看:173
本文介绍了Django南:在数据迁移中改变字段类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将一个字段从 CharField 更改为 IntegerField 。字段名称保持不变。新创建的字段将基于旧字段。例如,如果旧字段为L,则它将具有数字1。如何在 forward()函数中完成这个?

I'm changing a field from CharField to IntegerField. The field name remains the same. The newly created field will be based off the old field. For example, if the old field was "L", it would have the number "1" instead. How can I accomplish this in the forwards() function?

推荐答案

正确的方法是将其分解为三个迁移:

The correct way to do it would be to break this into three migrations:


  1. 第一个模式迁移以添加新的 IntegerField 字段。

  2. 随后进行数据迁移,将源自 CharField 的数据转换为 IntegerField

  3. 最后的模式迁移以移除现在未使用的 CharField

  1. A first schema migration to add the new IntegerField field.
  2. Followed by a data migration to convert the data originating from the CharField to the IntegerField
  3. And a final schema migration to remove the now unused CharField.

如果您想要新添加的 IntegerField 与要删除的 CharField 具有相同的名称。

A fourth one might be required if you want your newly added IntegerField to have the same name as the to-be-removed CharField.

给定项目状态,其中 IntegerField 尚未添加到模型文件中,您应该按照以下步骤继续执行:

Given a project state where the IntegerField is not yet added to you model file you should proceed by following these steps:


  1. 向您的模型添加 IntegerField

  2. 为应用程序创建模式迁移包含你的模型。

  3. 创建一个数据迁移(使用 datamigration),你可能需要为这个新添加的字段指定一个默认值)。在新创建的 DataMigration 类的 forward()方法中,记录您的逻辑转换您的数据。尝试使用更新管理方法,而不是迭代,如果可能的话,覆盖所有的数据库行。如果您使用 dict (说 {'L':1,...} )声明转换逻辑此时应该很容易实现 backwards(),因为操作是可逆的。这是一个很好的练习,以确保您没有忽视 forward()中的边缘案例 - 它过去帮助了我很多次。

  4. 从您的模型中删除 CharField

  5. 按照顺序为包含模型的应用程序创建模式迁移到 DROP 现在未使用的列。

  1. Add the IntegerField to you model.
  2. Create a schema migration for the application containing your model. You might need to specify a default value for your newly added field here if it's not null.
  3. Create a data migration (using datamigration) for the application containing your model. In the forwards() method of the newly created DataMigration class write down your logic to convert your data. Try to use the update manager method instead of iterating overt all your database row if possible. If you declare your conversion logic using a dict (say {'L': 1, ...}) it should be pretty easy to also implement backwards() at this time, given the operation is invertible. It's also a good exercise to make sure you've not overlooked an edged case in forwards() -- it helped me quite a few times in the past.
  4. Remove the CharField from your model.
  5. Create a schema migration for the application containing your model in order to DROP the now unused column.

你打破了这个操作进入三个迁移,而不是在一个空白的模板中写下你的整个逻辑有两个优点:

The fact that you broke this operation into three migrations instead of writing down your whole logic in a blank template have a couple advantages:


  1. 自动生成的DDL操作:code> ADD / DROP 逻辑已由南方自动生成,您不必担心在数据库列中引入打字错误。

  2. 完全可逆的操作:由于您已花费时间为转换步骤实施 DataMigration.backwards()能够完全扭转整个操作。这可以方便测试,如果您需要回滚到以前的代码版本,并且在更新生产代码库时可以使用安全的网络。

  3. 操作原理:每个操作是孤立运行的,它自己的事务不会让你在数据库和你的南移动之间处于不一致的状态。例如,如果所有操作都是在单个迁​​移中执行(在这种情况下,在相同的 forward()方法中),并且在数据迁移步骤期间引发了异常(例如 KeyError ,因为转换中的未处理的值 dict )。如果您使用不支持事务性模式更改的 ORDBMS ,则无法在修复数据迁移部分后立即重新运行迁移,您可以自己必须手动删除新添加的 IntegerField 列。再次,这是您在迁移生产数据库时不想处理的那种事情。

  4. 执行干运行的能力:迁移生产数据库时也非常方便。 / li>
  1. Auto-generated DDL operations: The ADD/DROP logic have been automatically generated by South and you don't have to worry about introducing a typo in a database column.
  2. Completely reversible operation: Given you've taken the time to implement DataMigration.backwards() for the conversion step you should be able to completely reverse the whole operation. This can be handy for testing purpose, if you need to rollback to a previous revision of your code and as safe net when updating a production code base.
  3. Atomicity of operations: The fact that each operation is isolated and run in it's own transaction won't leave you in an inconsistent state between your database and your South migration. For example, if all operations were performed in a single migration (in the same forwards() method in this case) and an exception was raised during the data migration step (say a KeyError because of an unhandled value in your conversion dict). If you're using a ORDBMS that doesn't support transactional schema alteration you wouldn't be able to re-run you migration immediately after fixing the data-migration part, you'd have to manually drop the newly added IntegerField column yourself. Again, that's the kind of thing you don't want to deal with when migrating a production database.
  4. Ability to perform a dry-run: Also quite handy when migrating a production database.

这篇关于Django南:在数据迁移中改变字段类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆