django 如何干净地将布尔字段迁移到字符字段

bksxznpy  于 2023-03-09  发布在  Go
关注(0)|答案(3)|浏览(133)

我有以下型号:

class Teacher(models.Model)
    tenured = models.BooleanField(default=False)

我想把这个BooleanField迁移到一个带有['No', 'Pending', 'Yes']选项的CharField

class Teacher(models.Model)
    TENURE_CHOICES =  [(choice,choice) for choice in ['No', 'Pending', 'Yes']]
    tenured = models.CharField(max_length=7, default='No', choices=TENURE_CHOICES)

现在,由于我已经为这个模型提供了1000多条记录,我希望在迁移时将它们从布尔值迁移到'Yes'/'No'值。
如何做到这一点,而不必存储此表的备份并在迁移发生后重新应用?是否可以将此操作作为迁移过程的一部分?

wyyhbhjk

wyyhbhjk1#

您可以使用makemigrations命令创建迁移,布尔值将转换为字符,“1”表示True,“0”表示False。之后,您可以编写简单的命令将所有“0”转换为“否”,将所有“1”转换为“是”,甚至从数据库级别进行转换。

from authorization.models import TestModel
TestModel.objects.create(example_bool=True)
<TestModel: TestModel object (1)>
TestModel.objects.create(example_bool=True)
<TestModel: TestModel object (2)>
TestModel.objects.create(example_bool=True)
<TestModel: TestModel object (3)>
TestModel.objects.create(example_bool=False)
<TestModel: TestModel object (4)>
TestModel.objects.create(example_bool=False)
<TestModel: TestModel object (5)>
for x in TestModel.objects.all():
    print(x.example_bool)

1
1
1
0
0
xv8emn3q

xv8emn3q2#

我们在django上运行了一个零停机应用程序,所以我们永远不能删除同一部署中的字段,因为要更改模型以反映删除。
要迁移,我们重命名旧字段并添加新字段。您可以使用此方法首先重命名并添加新字段,并根据docs https://docs.djangoproject.com/en/4.0/howto/writing-migrations/进行自定义迁移。
因此,您保留数据,直到您确定一切正常。
一旦您满意了,就从模型-〉部署-〉进行迁移-〉再次部署中删除重命名的字段。
这种变体是零停机兼容的,并且具有不需要表的备份或拷贝的优点。

q3qa4bjr

q3qa4bjr3#

继@PTomasz的更简单(但不是零停机)解决方案之后,可以修补以下迁移文件以运行它:

# add this:
def set_tenure_choices(apps, _schema_editor):
    Teacher = apps.get_model('main', 'Teacher')
    for tc in Teacher.objects.all():
        if tc.tenured == '1':
            tc.tenured = 'Yes'
        elif tc.tenured == '0':
            tc.tenured = 'No'
        tc.save()

class Migration(migrations.Migration):
    operations = [
        migrations.AlterField(
            model_name='teacher',
            name='tenured',
            field=models.CharField(default='No', max_length=7),
        ),
        # Add this line:
        migrations.RunPython(set_tenure_choices),
    ]

(Note在Django w/ mysql中,所有的CharField(即使有选项)都存储为VarChar,因此设置max_length=255而不是7不会增加所需的存储空间,但如果将来添加其他选项,可能会保存迁移)

相关问题