在 Django 中向后迁移 DeleteModel 时出错

Error during backward migration of DeleteModel in Django

我在 Django 1.11 和 PostgreSQL 中有两个一对一关系的模型。这两个模型在models.py中定义如下:

class Book(models.Model):
    info = JSONField(default={})


class Author(models.Model):
    book = models.OneToOneField(Book, on_delete=models.CASCADE)

关于这些模型的自动创建的迁移文件如下:

class Migration(migrations.Migration):

    dependencies = [
        ('manager', '0018_some_migration_dependency'),
    ]

    operations = [
        migrations.CreateModel(
            name='Book',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('info', JSONField(default={})),
            ],
        ),
        migrations.AddField(
            model_name='author',
            name='book',
            field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='manager.Book'),
        ),
    ]

这些实现已经成功运行。除了这次迁移,我们还有一些与我们项目的其他任务相关的其他额外迁移。

由于我们今天进行了设计更改,我们决定将所有图书信息数据移至我们的云存储中。为此,我实现了如下自定义迁移代码:

def push_info_to_cloud(apps, schema_editor):

    Author = apps.get_model('manager', 'Author')
    for author in Author.objects.all():
        if author.book.info is not None and author.book.info != "":

            # push author.book.info to cloud storage

            author.book.info = {}
            author.book.save()


def pull_info_from_cloud(apps, schema_editor):

    Author = apps.get_model('manager', 'Author')
    Book = apps.get_model('manager', 'Book')
    for author in Author.objects.all():

            # pull author.book.info back from cloud storage

            book = Book.objects.create(info=info)
            author.book = book
            author.save()


class Migration(migrations.Migration):

    dependencies = [
        ('manager', '0024_some_migration_dependency'),
    ]

    operations = [
        migrations.RunPython(push_info_to_cloud, pull_info_from_cloud)
    ]

正如代码本身所说,此迁移将每个非空书籍信息数据推送到我们的云存储,并用数据库中的空字典替换它。我已经来回测试了此迁移,并确保向前和向后迁移都成功。

然后,为了去掉 Book table 和 bookAuthor table,我删除了 Book模型和 Author 模型中的 OneToOneField 书籍字段和 运行 manage.py makemigrations,导致以下自动生成的迁移代码:

class Migration(migrations.Migration):

    dependencies = [
        ('manager', '0025_some_migration_dependency'),
    ]

    operations = [
        migrations.RemoveField(
            model_name='user',
            name='book',
        ),
        migrations.DeleteModel(
            name='Book',
        ),
    ]

运行 manage.py migrate 确实有效。最后删除了Booktable和Authortable的book

现在,问题是;当我想迁移回 0024_some_migration_dependency 时,在执行最新的迁移文件时出现以下错误:

  Unapplying manager.0026_auto_20190503_1702...Traceback (most recent call last):
  File "/home/cagrias/Workspace/Project/backend/venv/lib/python3.6/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
psycopg2.IntegrityError: column "book_id" contains null values

我看过这个。为了尝试,我这次使用 blank=True, null=True 参数手动重新创建 Book 模型和 Author 模型的 OneToOneField book 字段。但是在我成功应用上面的迁移之后,我在向后迁移时遇到了同样的异常。

可能是什么问题?

我已经通过更改迁移顺序设法解决了问题。

正如我在问题中提到的,我通过将 blank=True, null=True 参数添加到 infobook 字段来应用 。但是它的相关迁移文件是在将我们的图书信息移动到云存储的迁移文件之后创建的。当我更改了这两个迁移文件的顺序后,问题就解决了。