问题:Django-DB-Migrations:无法更改表,因为它具有未决的触发事件
我想从TextField中删除null = True:
- footer=models.TextField(null=True, blank=True)
+ footer=models.TextField(blank=True, default='')
我创建了一个架构迁移:
manage.py schemamigration fooapp --auto
由于某些页脚列包含,NULL
因此error
在运行迁移时会得到以下信息:
django.db.utils.IntegrityError:“页脚”列包含空值
我将其添加到架构迁移中:
for sender in orm['fooapp.EmailSender'].objects.filter(footer=None):
sender.footer=''
sender.save()
现在我得到:
django.db.utils.DatabaseError: cannot ALTER TABLE "fooapp_emailsender" because it has pending trigger events
怎么了?
回答 0
造成这种情况的另一个原因可能是因为您尝试将一列设置为NOT NULL
实际上已经具有NULL
值的时间。
回答 1
每次迁移都在事务内部。在PostgreSQL中,您不得在一个事务中更新表然后更改表模式。
您需要拆分数据迁移和架构迁移。首先使用以下代码创建数据迁移:
for sender in orm['fooapp.EmailSender'].objects.filter(footer=None):
sender.footer=''
sender.save()
然后创建架构迁移:
manage.py schemamigration fooapp --auto
现在,您有两个事务,并且应该在两个步骤中进行迁移。
回答 2
刚刚遇到这个问题。您还可以在模式迁移中使用db.start_transaction()和db.commit_transaction()将数据更改与模式更改分开。可能不那么干净,无法进行单独的数据迁移,但是在我的情况下,我需要架构,数据,然后再进行另一种架构迁移,因此我决定一次完成所有操作。
回答 3
在操作中,我将SET约束:
operations = [
migrations.RunSQL('SET CONSTRAINTS ALL IMMEDIATE;'),
migrations.RunPython(migration_func),
migrations.RunSQL('SET CONSTRAINTS ALL DEFERRED;'),
]
回答 4
您正在更改列架构。该页脚列不能再包含空白值。该列中很可能已经有空白值存储在数据库中。Django将使用migration命令将数据库中的空白行从空白更新为现在的默认值。Django尝试更新页脚列为空值的行,并在看起来相同的同时更改架构(我不确定)。
问题是您无法更改试图同时更新其值的列模式。
一种解决方案是删除迁移文件以更新架构。然后,运行脚本以将所有这些值更新为默认值。然后重新运行迁移以更新架构。这样,更新已完成。Django迁移仅更改架构。