Django:如何将CharField转换为TextField并保留数据

14

有没有一种方法可以将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)

但是DB_MAX_CHAR_LENGTH为500,而这个字段有时可能超过该长度,因此我想执行以下操作:

class TestLog(models.Model):
    failed_reqs = models.TextField(blank=True)
    passed_reqs = models.TextField(blank=True)
我该如何做到这一点并在生产数据库中保持我的数据完好无损? Djangobook详细介绍了如何添加和删除字段,我已经尝试使用South来完成这个过程,但是South给了我一个错误,并且从错误之前的输出看来,似乎South正在删除并重新创建数据库。这就是South的数据迁移的全部内容吗?

这是关于数据库限制的问题,但我在寻找如何将模型字段显示为文本区域而不是输入[type = text]时发现了这个问题。如果您只想要表单使用不同的HTML控件,请参见:https://docs.djangoproject.com/en/dev/ref/forms/widgets/#specifying-widgets。如果问题更深入(例如在问题中),请使用South迁移。 - Tomasz Gandor
3个回答

24

这可以通过Django迁移(1.7+)解决。如果您将CharField类型更改为TextField,则生成的迁移是AlterField,它可以完成正确的操作。


5

假设你可以访问数据库,因为你提到了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;

在进行这些更改之前,强烈建议备份您的数据库。


最好在迁移中编写代码,这样你的数据库(或者你希望的 SQL 方言)就不会受到影响。 - WisdomPill
这是一个关于如何创建Django数据迁移的小教程,链接在这里:https://simpleisbetterthancomplex.com/tutorial/2017/09/26/how-to-create-django-data-migrations.html - WisdomPill

5

一开始,我会继续研究一个南方方法。 我尝试的工作流程如下:

1)South模式迁移以创建两个名为“failed_reqs_txt”和“passed_reqs_txt”的新TextField字段。

2)创建数据迁移以将数据从旧字段迁移到新字段

3)创建模式迁移以删除原始的“failed_reqs”和“passed_reqs”字段。

----如果您需要使字段与原始名称相同,则可以进行以下步骤:

4)创建模式迁移,将“failed_reqs”和“passed_reqs”添加为TextFields

5)创建数据迁移以从“failed_reqs_txt”和“passed_reqs_txt”迁移到“failed_reqs”和“passed_reqs”字段。

6)创建模式迁移以删除“failed_reqs_txt”和“passed_reqs_txt”字段。

虽然这是很多次迁移,但将每个更改分解为原子迁移。我会首先尝试这个。我不确定为什么South会删除并重建数据库。 您在将South添加到项目中时是否运行了convert_to_south选项?我认为这会伪造迁移并让South知道它正在使用现有项目而不是新项目。

另外,您可以直接对数据库进行一些ALTERS来更改列类型,然后将model.py从CharField更新为TextField。Postgres,据说支持隐式更改数据类型。 (请参见第5.5.6节)。我不确定mysql,但我认为它的工作方式相同。 (CharField到TextFiled应该是兼容的转换)

无论如何,在进行任何此类更改之前,请备份您的数据。希望这可以帮助。


谢谢,这个问题最终很容易地通过Toad和/或SQL语句直接在数据库中切换解决了,但是我们将来需要使用South,所以我很感激您的写作。 - Nathan
1
这是正确的方法,适用于不同的底层数据库。即使看起来很长,它也非常合乎逻辑。只需要三个迁移步骤:1)模式+数据:创建字段,并用旧值初始化它们,2)转储旧字段,3)将新字段重命名为旧名称。我不确定,但你甚至可以在两个迁移步骤中完成,而且可以轻松地编写反向迁移步骤。 - Tomasz Gandor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接