Django新的ForeignKey字段基于现有字段

时间:2015-08-10 07:49:00

标签: python django model foreign-keys default

我正在尝试执行以下操作,但无法在文档或stackoverflow上找到一个好的解决方案。

我有一个拥有此模型的约1000名用户的现有数据库:

class Student(AbstractBaseUser):
    email = models.EmailField(verbose_name='email address', max_length=255, unique=True)
    school = models.CharField(max_length=255,null=True, blank=True)
    ...

但我最终决定使用一个单独的模型来处理学校:

class Student(AbstractBaseUser):
    email = models.EmailField(verbose_name='email address', max_length=255, unique=True)
    school = models.ForeignKey('School')

class School(models.Model):
    name = models.CharField(max_length=255,unique=True)

我如何处理所有现有的学生,知道对于未来的学生,我会直接在学校表格中询问学校的外键?

2 个答案:

答案 0 :(得分:3)

最简单的解决方案是创建自动迁移,这将是这样的(仅列出操作):

    operations = [
        migrations.CreateModel(
            name='School',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('name', models.CharField(unique=True, max_length=255)),
            ],
        ),
        migrations.AlterField(
            model_name='Student',
            name='school',
            field=models.ForeignKey(blank=True, to='testapp.School', null=True),
        ),
    ]

我已经编辑了模型Student,所以现在ForeignKey可以为null,如果您确定每个Student都会分配School,则可以在迁移结束时删除AlterField中的空值。

现在您应该通过将AlterField拆分为3个单独的操作(按顺序)来编辑此迁移:RenameField(将现有的学校字段重命名为例如school_name),AddField(将ForeignKey添加到学校模型)和RemoveField(删除旧的,不需要的字段)。

现在,在AddFieldRemoveField之间插入RunPython操作,并在该操作中运行将创建新School对象的代码(如果数据库中没有此类对象)并将对象分配给你的Student

简单来说:迁移会创建名为School的新模型,将旧字段school重命名为school_name,创建新字段schoolForeignKey为模型School中的Student},遍历所有学生创建新School个对象并将其分配给学生,最后一步,删除旧的school_name字段(以前称为{{1} }})。

您还可以向school提供反向代码,以便您可以在不丢失数据的情况下撤消迁移。

答案 1 :(得分:0)

如果您想要使用ORM进行实时操作,可以将Student.school字段重命名为Student.school_old,然后添加Student.school ForeignKey,并使用以下代码段进行制作确保数据正常:

for student in Student.objects.filter(school__isnull=False):
    try:
        school = School.objects.get(name=student.school_old)
    except School.DoesNotExist:
        school = School.objects.create(name=student.school_old)
    student.school = school
    student.save()