Django south:在数据迁移中改变字段类型

时间:2014-03-24 02:25:07

标签: django django-south

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

2 个答案:

答案 0 :(得分:17)

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

  1. 用于添加新IntegerField字段的第一个架构迁移。
  2. 随后进行数据迁移,将源自CharField的数据转换为IntegerField
  3. 最后的架构迁移,以删除现在未使用的CharField
  4. 如果您希望新添加的IntegerField与要移除的CharField具有相同的名称,则可能需要第四个。

    如果项目状态中IntegerField尚未添加到模型文件中,则应按照以下步骤继续:

    1. IntegerField添加到您的模型中。
    2. 为包含模型的应用程序创建架构迁移。 如果新添加的字段不为空,您可能需要为其添加默认值。
    3. 为包含模型的应用程序创建数据迁移(使用datamigration)。在新创建的forwards()类的DataMigration方法中,记下转换数据的逻辑。尝试使用update管理器方法,而不是在可能的情况下迭代所有数据库行。如果您使用dict(例如{'L': 1, ...})声明转换逻辑,那么此时应该很容易实现backwards(),因为操作是可逆的。这也是一个很好的练习,以确保你没有忽略forwards()中的一个边缘案例 - 它在过去帮助了我很多次。
    4. 从模型中删除CharField
    5. 为包含您的模型的应用程序创建架构迁移,以便DROP现在未使用的列。
    6. 您将此操作分为三次迁移而不是将整个逻辑写入空白模板这一事实有一些优势:

      1. 自动生成的DDL操作:南方已自动生成ADD / DROP逻辑,您无需担心在数据库列中引入拼写错误。
      2. 完全可逆的操作:如果您花时间为转换步骤实施DataMigration.backwards(),您应该能够完全颠倒整个操作。如果您需要回滚到代码的先前版本并且在更新生产代码库时作为安全网络,这对于测试目的来说非常方便。
      3. 操作的原子性:每个操作被隔离并在其自己的事务中运行的事实不会使您在数据库和南迁移之间处于不一致状态。例如,如果所有操作都是在单个迁​​移中执行的(在本例中采用相同的forwards()方法),并且在数据迁移步骤期间引发了异常(比如KeyError,因为未处理的值您的转化dict)。如果您使用的ORDBMS不支持事务模式更改,则在修复数据迁移部分后无法立即重新运行迁移,您必须手动删除新添加的数据迁移部分IntegerField列自己。同样,这是您在迁移生产数据库时不想处理的事情。
      4. 执行干运行的能力:在迁移生产数据库时也非常方便。

答案 1 :(得分:1)

对于同样的情况,我只需要3个步骤。

1)将文件类型从CharField更改为IntegerField,

2)ALTER TABLE the_table ALTER COLUMN col_name TYPE integer USING(col_name :: integer); 或

ALTER TABLE the_table ALTER COLUMN col_name TYPE integer USING(trim(col_name):: integer); #以防你的Char或Text字段中有空格。如果你的表中有数据,那应该是整数字符串。

3)现在应用迁移。