gpt4 book ai didi

使用 RunPython 提交更改的 Django 迁移

转载 作者:行者123 更新时间:2023-12-03 11:46:25 24 4
gpt4 key购买 nike

我想在我的模型之一中更改当前可以具有 NULL 值的外键,使其不可为空。

我删除了 null=True从我的领域跑 makemigrations
因为我正在修改一个表,该表已经包含在该字段中包含 NULL 值的行,所以我被要求立即提供一次性值或编辑迁移文件并添加 RunPython手术。

我的 RunPython 操作在 AlterField 之前列出操作并为此字段执行所需的更新,因此它不包含 NULL 值(仅包含已包含 NULL 值的行)。

但是,迁移仍然失败并出现此错误:django.db.utils.OperationalError: cannot ALTER TABLE "my_app_site" because it has pending trigger events
这是我的代码:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

def add_default_template(apps, schema_editor):
Template = apps.get_model("my_app", "Template")
Site = apps.get_model("my_app", "Site")

accept_reject_template = Template.objects.get(name="Accept/Reject")
Site.objects.filter(template=None).update(template=accept_reject_template)

class Migration(migrations.Migration):

dependencies = [
('my_app', '0021_auto_20150210_1008'),
]

operations = [
migrations.RunPython(add_default_template),
migrations.AlterField(
model_name='site',
name='template',
field=models.ForeignKey(to='my_app.Template'),
preserve_default=False,
),
]

如果我理解正确,当字段被更改为不可为空但该字段包含空值时,可能会发生此错误。
在那种情况下,我能想到为什么会发生这种情况的唯一原因是 RunPython在运行 AlterField 之前,操作事务没有“提交”数据库中的更改.

如果这确实是原因 - 我如何确保更改反射(reflect)在数据库中?
如果不是 - 错误的原因是什么?

谢谢!

最佳答案

发生这种情况是因为 Django 将约束创建为 DEFERRABLE INITIALLY DEFERRED :

ALTER TABLE my_app_site
ADD CONSTRAINT "[constraint_name]"
FOREIGN KEY (template_id)
REFERENCES my_app_template(id)
DEFERRABLE INITIALLY DEFERRED;
这告诉 PostgreSQL 不需要在每个命令后立即检查外键,但可以推迟到事务结束。
因此,当事务修改内容和结构时,会在结构更改的同时检查约束,或者安排在更改结构后进行检查。这两种状态都不好,数据库将中止事务而不是做出任何假设。
您可以通过调用 SET CONSTRAINTS ALL IMMEDIATE 指示 PostgreSQL 立即检查当前事务中的约束。 ,因此结构更改不会成为问题(请参阅 SET CONSTRAINTS 文档)。您的迁移应如下所示:
operations = [
migrations.RunSQL('SET CONSTRAINTS ALL IMMEDIATE',
reverse_sql=migrations.RunSQL.noop),

# ... the actual migration operations here ...

migrations.RunSQL(migrations.RunSQL.noop,
reverse_sql='SET CONSTRAINTS ALL IMMEDIATE'),
]
第一个操作用于应用(向前)迁移,最后一个用于取消应用(向后)迁移。
编辑:约束延迟对于避免插入排序很有用,特别是对于自引用表和具有循环依赖关系的表。所以弯曲 Django 时要小心。
后期编辑:在 Django 1.7 和更新版本上,有一个特殊的 SeparateDatabaseAndState 允许在同一迁移中更改数据和结构的操作。在诉诸上面的“立即设置约束”方法之前尝试使用此操作。例子:
operations = [
migrations.SeparateDatabaseAndState(database_operations=[
# put your sql, python, whatever data migrations here
],
state_operations=[
# field/model changes goes here
]),
]

关于使用 RunPython 提交更改的 Django 迁移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28429933/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com