如何将字段从一个模型移动到另一个模型,并仍然保留数据?

时间:2016-05-11 18:51:49

标签: python django django-models

为了简化,我有一个模型,比方说,

class Parent(models.Model):
    field_a = models.CharField(max_length=40)

和另一个包含图像字段的模型,它通过外键将自身绑定到父实例:

class ParentPicture(models.model):
    parent = models.ForeignKey(Parent)
    picture = models.ImageField(upload_to=upload_path)
    is_used = models.BooleanField(default=False)

最初的计划是支持父母的多张图片,并且一次只能使用一张图片,但是现在,我想支持一张图片,并将其包含在父模型中,以便ParentPicture可以被销毁,Parent看起来像这样:

class Parent(models.Model):
    field_a = models.CharField(max_length=40)
    picture = models.ImageField(upload_to=upload_path)

我不确定将picture字段移到新模型的最佳方法,并且包含来自ParentPicture的{​​{1}}标记的实例。< / p>

有没有一种简单的方法可以自动使用Django,或者我需要对is_used模型进行更改,迁移更改,然后运行脚本以完成Parent模型并适当地复制,然后完成后,删除ParentPicture模型?

感谢您提供任何帮助/建议!

2 个答案:

答案 0 :(得分:9)

我认为没有&#39;自动&#39;移动场地的方法,所以你可以这样做:

  1. picture字段添加到Parent
  2. 生成并运行架构迁移
  3. 编写并运行data migration以使用模型picture
  4. 中的值填充新的ParentPicture字段
  5. 删除旧的/过时的模型/字段,生成新的模式迁移并运行它

答案 1 :(得分:2)

这是一个多步骤的过程。首先,您需要按如下方式添加字段,然后执行./manage.py makemigrations

class Parent(models.Model):
    field_a = models.CharField(max_length=40)    
    picture = models.ImageField(upload_to=upload_path)
    is_used = models.BooleanField(default=False)

第二步,你有两个选择。第一种是创建一个migrations.RunPython,它查询ParentPicture表并使用其中的值更新Parent表。这不会涉及原始sql,但效率低下。另一方面,如果你只有几行就没关系。

  for p in ParentPicture.objects.all():
      Parent.objects.filter(pk = p.parent_id
           ).update(picture=p.picture, is_used=p.is_used)

另一种方法是使用migrations.RunSQL UPDATE JOIN类型的查询。如果您有大量记录,这将是有效的并且建议使用。在mysql中,您的查询可能如下所示:

UPDATE app_parent p 
   INNER JOIN app_parentpicture pp on
      p.id = pp.parent_id
   SET p.picture = pp.picture, 
      p.is_used = pp.is_used

第3步,你真的需要在这个阶段放弃旧桌子吗?为什么不等到完成一些彻底的测试?