Django:在数据不丢失的情况下将CharField转换为TextField
有没有办法把一个字符字段(CharField)改成文本字段(TextField),而且还能保持这个列里的数据不变呢?
现在我有以下的内容:
class TestLog(models.Model):
failed_reqs = models.CharField(max_length=DB_MAX_CHAR_LENGTH, blank=True)
passed_reqs = models.CharField(max_length=DB_MAX_CHAR_LENGTH, blank=True)
但是目前这个字符字段的最大长度是500,结果发现有时候这个字段的数据会超过这个长度,所以我想改成:
class TestLog(models.Model):
failed_reqs = models.TextField(blank=True)
passed_reqs = models.TextField(blank=True)
我该怎么做才能在生产数据库中保持我的数据不变呢?
Djangobook 里详细说明了如何添加和删除字段,我也试着用 South 来做到这一点,但 South 给我报了错,查看报错前的输出,似乎 South 是在删除然后重新创建数据库。这就是 South 的 数据迁移 吗?
3 个回答
首先,我会继续考虑使用South这个工具。以下是我会尝试的步骤:
1) 使用South进行模式迁移,创建两个新的文本字段,名字可以叫“failed_reqs_txt”和“passed_reqs_txt”。
2) 创建一个数据迁移,把旧字段的数据迁移到新字段。
3) 创建一个模式迁移,删除原来的“failed_reqs”和“passed_reqs”字段。
---- 如果你需要字段的名字和原来的保持一致,我会接着进行:
4) 创建一个模式迁移,添加“failed_reqs”和“passed_reqs”作为文本字段。
5) 创建一个数据迁移,把“failed_reqs_txt”和“passed_reqs_txt”的数据迁移到“failed_reqs”和“passed_reqs”字段。
6) 创建一个模式迁移,删除“failed_reqs_txt”和“passed_reqs_txt”字段。
虽然这需要很多次迁移,但这样可以把每个变化拆分成小的迁移步骤。我会先尝试这个方法。我不太明白为什么South会删除并重新创建数据库。你在给项目添加South时,有运行“convert_to_south”这个选项吗?我觉得这个选项可以模拟一次迁移,让South知道它是在处理一个已有的项目,而不是一个新项目。
另外,你也可以直接对数据库进行一些ALTER操作,来改变字段类型,然后把model.py中的CharField更新为TextField。Postgres据说支持这样隐式地改变数据类型。(见第5.5.6节。)我不太确定mysql,但我觉得应该也是一样的。(从CharField到TextField应该是兼容的转换)
无论如何,在进行任何这样的更改之前,我会备份我的数据。希望这些信息对你有帮助。
这个问题可以通过Django的迁移功能来解决(1.7及以上版本)。如果你把字段类型从字符字段(CharField)改成文本字段(TextField),生成的迁移文件会是AlterField,这样就能正确处理这个变化。
假设你可以访问数据库,正如你提到的Django在添加和删除列时的方式,我列出了Postgresql和MySQL的操作方法,因为你没有说明你使用的是哪种数据库。
Postgresql:
BEGIN;
ALTER TABLE "TestLog"
ALTER COLUMN "failed_reqs" TYPE TEXT,
ALTER COLUMN "passed_reqs" TYPE TEXT;
COMMIT;
MySQL:
BEGIN;
ALTER TABLE TestLog
MODIFY failed_reqs TEXT NULL,
MODIFY passed_reqs TEXT NULL;
COMMIT;
我强烈建议在进行这些更改之前备份你的数据库。