Django迁移-通过应对现有字段填充空白字段

时间:2020-11-08 12:46:40

标签: python django database-migration django-migrations

在更改模型后进行迁移时遇到问题。我已经将exisitnig DateField( lectures_begginning )从null=true更改为null=false。现在,我必须填充旧条目。幸运的是,我有一个现有的DateField( semester_begginning ),该字段始终设置为null=false。通常这两个时间相差4-5天,因此我可以复制 semester_beggining

class Semester(models.Model):

    lectures_beginning = models.DateField(
        null=False, verbose_name='Class start day')
    semester_beginning = models.DateField(
        null=False, verbose_name='Semester start day')

如何更改迁移,以便仅在后者为NULL时将 semester_beginning 的值复制到 lectures_beginning

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('courses', '0034_auto_20201106_2039'),
    ]

    operations = [
        migrations.AlterField(
            model_name='semester',
            name='lectures_beginning',
            field=models.DateField(verbose_name='Dzień rozpoczęcia zajęć'),
        ),
    ]

1 个答案:

答案 0 :(得分:0)

您应该使用make_migration创建一个空迁移。然后将RunPython操作添加到新迁移的operations列表中。

以下是一个示例(来自Django documentation):

from django.db import migrations

def combine_names(apps, schema_editor):
    # We can't import the Person model directly as it may be a newer
    # version than this migration expects. We use the historical version.
    Person = apps.get_model('yourappname', 'Person')
    for person in Person.objects.all():
        person.name = '%s %s' % (person.first_name, person.last_name)
        person.save()

class Migration(migrations.Migration):

    dependencies = [
        ('yourappname', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(combine_names),
    ]

如注释中所述,您必须使用apps来检索Model实例,因为您需要一个与迁移历史记录中特定点的数据库架构兼容的版本。

在您的情况下,您可以查询Semester为空的所有lectures_beginning对象。然后迭代结果列表中的对象,复制该对象的字段,然后保存该对象。 (我认为没有一种聪明的方法可以避免编写一些python代码。)

请注意,此数据迁移需要在使用AlterField进行迁移之前进行。我建议保持将架构和数据迁移操作放在单独的迁移中。 (我不知道如果您尝试将它们结合起来是否可行。)