在South中,我可以将旧列的值复制到新列吗?
我有一个Django模型,它是一个子类,我想把它的父类换成一个和原来非常相似的类。具体来说,新的父类描述的是同一个对象,并且有相同的主键。我该怎么做才能让South创建一个新的OneToOne字段,并把旧字段里的值复制到新字段里呢?
1 个回答
在South这个工具里,有两种迁移方式:一种是结构迁移,另一种是数据迁移。
当你创建好结构迁移后,接下来要创建一个对应的数据迁移:
./manage.py datamigration <app> <migration_name>
这时候不要运行迁移(还不需要)。相反,打开你刚才创建的迁移文件。
你会看到一个叫做 forwards()
的方法。在这个方法里,你需要定义一个过程,把旧表里的数据复制到新表里。
如果你要把某个表的结构改得更复杂,通常的做法是先进行两次结构迁移,然后再进行一次数据迁移:第一次结构迁移是添加新字段,数据迁移是把旧字段的数据转到新字段里,最后第二次结构迁移则是删除旧字段。通过 forwards()
方法,你可以对数据库做很多事情,只要记得你在访问哪个结构(旧的还是新的)。一般来说,你只会从 orm.
相关的地方读取数据,而写入则使用传统的Django访问方式。
South数据迁移教程对此有详细的讲解。它教你如何使用South的 orm
来访问数据库,这样在结构迁移之前就能使用数据库,而不会因为Django不理解某些字段而出错。
如果你要重命名一个类,这可能会比较麻烦——这涉及到创建新表、从旧表迁移到新表,然后删除旧表。South可以做到这一点,但可能需要多次进行结构和数据迁移。
South还有一个 backwards()
方法,可以让你把数据库表恢复到之前的状态。在某些情况下,这可能是做不到的;因为新表可能记录了一些在降级时会丢失的信息。如果你不在调试模式下,我建议在 backwards()
方法里抛出一个异常。