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

ech*_*ion 7 python django django-models

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

class Parent(models.Model):
    field_a = models.CharField(max_length=40)
Run Code Online (Sandbox Code Playgroud)

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

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

最初的计划是为父母支持多张图片,并且在任何时候只使用一张图片,但现在,我想支持一张图片,并将其包含在父模型中,这样ParentPicture就可以了被毁坏了,Parent看起来像这样:

class Parent(models.Model):
    field_a = models.CharField(max_length=40)
    picture = models.ImageField(upload_to=upload_path)
Run Code Online (Sandbox Code Playgroud)

我不确定将picture字段移动到新模型的最佳方法,并包含ParentPicture具有is_used标志的实例.

是否有一种简单的方法可以使用Django自动执行此操作,或者我是否需要对Parent模型进行更改,迁移更改,然后运行脚本以完成ParentPicture模型并进行相应的复制,然后在完成之后,删除该ParentPicture模型?

感谢您的帮助/建议!

tri*_*het 10

我认为没有"自动"方式来移动这个领域,所以你可以这样做:

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


e4c*_*4c5 5

这是一个多步骤的过程。首先,您需要添加字段如下,然后执行 ./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)
Run Code Online (Sandbox Code Playgroud)

对于第二步,您有两个选择。第一个是创建一个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)
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用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
Run Code Online (Sandbox Code Playgroud)

第三步,现阶段你真的需要删除旧表吗?为什么不等到完成一些彻底的测试之后呢?