【问题标题】:Error during backward migration of DeleteModel in Django在 Django 中向后迁移 DeleteModel 时出错
【发布时间】:2019-09-22 05:52:43
【问题描述】:

我在 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)
    ]

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

然后,为了摆脱Author 表中多余的Book 表和book 列,我删除了Author 模型中的Book 模型和OneToOneField book 字段并运行@987654332 @,这导致以下自动生成的迁移代码:

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 确实有效。最终删除了Book表和Author表的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

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

可能是什么问题?

【问题讨论】:

    标签: python django postgresql psycopg2 django-migrations


    【解决方案1】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-17
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 2019-12-15
      • 1970-01-01
      • 1970-01-01
      • 2010-10-27
      相关资源
      最近更新 更多