通过 1.10 中的迁移播种数据

Seeding data through migration in 1.10

问题定义有点棘手,请耐心等待。

我有一个名为博客的模型。我有三个迁移。

0001_initial:为博客

创建table

0002_seed_data:将一些数据播种到此 table。要播种此数据,我使用:

all_blogs = Blog.objects.all()
 for blog in all_blogs.iterator():
  #some logic here
  blog.save()

0003_add_column: 添加一个新列'title'到这个table

当我 运行 0003_add_column0002_seed_data 已经 运行 在过去,它有效。

但是当我 运行 在空数据库上进行这些迁移时,它在 0002_seed_data 处失败,因为它无法在数据库中找到标题。它会给出类似于以下内容的错误:

django.db.utils.OperationalError: (1054, "Unknown column 'Blog.title' in 'field list'")

这对我来说就像先有鸡还是先有蛋的问题,因为 0002 无法 运行 直到 table 中不存在标题列。在 0003 中的 table 中有规定可以添加标题,但是不能 运行 直到 0002 有 运行。 一个简单的解决方案是更正顺序。这就是我过去一直在做的事情。但这意味着每次我向 table 添加一个新列时,它的顺序都必须更正。

快速搜索错误 returns 一些解决方案,其中大部分都谈到删除所有迁移并使用 makemigrations 重新进行迁移。这不能解决我的问题

那么有更好的方法吗?

您应该使用 SQL 命令来更改数据库中的任何内容。你可以使用 python 库,错误来了,因为你使用 Django class 模型,它有现在的标题字段,但是当它试图找到那个值时,那个时候没有值,所以最好从 SQL query 中获取值,执行您想对其执行的任何操作。

您没有显示您的迁移文件,但我猜您正在从您的模型文件中导入您的博客 class。如您所见,您不能这样做,因为它与迁移过程中此时的数据库状态不同步。

幸运的是,Django 迁移支持 "historical" 模型,可以根据数据库的状态正确表示模型。您无需导入模型,而是通过调用 apps.get_model() 在 RunPython 函数中以编程方式获取它。所以:

def my_function(apps, schema_editor):
    Blog = apps.get_model('myapp', 'Blog')
    all_blogs = Blog.objects.all()
    ...

请参阅 data migrations 上的文档。