我正在尝试执行以下操作,但无法在文档或 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)
我如何处理所有现有学生,因为我知道对于 future 的学生,我将直接在订阅表中询问学校外键?
最佳答案
最简单的解决方案是创建自动迁移,就像这样(仅列出操作):
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 中的 null 值
已分配。
现在您应该通过将 AlterField 拆分为 3 个单独的操作(按顺序)来编辑此迁移:RenameField
(将现有的学校字符字段重命名为例如 school_name),AddField
(将 ForeignKey 添加到学校模型)和 RemoveField
(删除旧的、不需要的字符字段)。
现在,插入 RunPython
AddField
和 RemoveField
之间的操作以及在该操作内运行的代码将创建新的 School 对象(如果数据库中没有这样的对象)并将对象分配给您的 Student
。
简单来说:迁移将创建新模型,命名为 School
,将旧字段 school
重命名为 school_name
,创建新字段 school
(ForeignKey
到 School
)在模型 Student
中,遍历所有学生创建新的 School
对象并将其分配给学生,最后一步,删除旧的 school_name
字段(以前名为 school
)。
您还可以向 RunPython
提供反向代码,这样您就可以在不丢失数据的情况下反向迁移。
关于python - Django new ForeignKey 字段基于现有字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31914222/