gpt4 book ai didi

mysql - 为什么 Django 在添加新列时删除 SQL DEFAULT 约束?

转载 作者:行者123 更新时间:2023-12-02 19:09:38 25 4
gpt4 key购买 nike

在最新的 Django (2.2) 中,当我向模型添加新字段时,如下所示:

new_field= models.BooleanField(default=False)

Django 为 MySQL 运行以下命令:

ALTER TABLE `app_mymodel` ADD COLUMN `new_field` bool DEFAULT b'0' NOT NULL;
ALTER TABLE `app_mymodel` ALTER COLUMN `new_field` DROP DEFAULT;
COMMIT;

虽然这在更新所有内容时有效,但这是非常有问题的,因为旧版本的应用程序在运行此迁移后无法再创建模型(它们不知道new_field)。为什么不只保留 DEFAULT 约束呢?

最佳答案

Why not just keep the DEFAULT constraint?

因为 Django 在应用程序级别处理默认模型字段选项,而不是数据库级别。所以真正的问题是为什么它设置 DEFAULT 约束。

关于第一点,Django 历史上不支持模型字段的数据库级默认值。一直有人对改变这一点感兴趣(关于这个主题的 first issue 已经有 18 岁了),当然其他框架(我认为是 Rails 和 SQLAlchemy )已经表明这是可能的。

最近 Django 有 added该选项带有一个名为 db_default 的单独字段选项。不过,default 的行为将保持不变,并且除了向后兼容性之外,还有充分的理由在应用程序级别处理默认值。如:表达任意复杂计算的能力;不必担心跨数据库引擎的细微不兼容性;能够在代码中实例化新实例并立即访问默认值;能够以表单形式向用户呈现默认值;等等。

现在,向现有数据库添加新的不可为空字段是一个非常不同的用例。在这种情况下,您必须为数据库提供默认值以使其执行操作。如果可以的话,makemigrations 将尝试从您的 default 选项推断出正确的值,如果不能,它将强制您从命令行指定一个值。因此 DEFAULT 修饰符用于此有限目的,然后被删除。

正如您所注意到的,Django 中缺乏数据库级默认设置可能会使持续部署变得更加困难。但解决方案相当简单:只需在迁移中自行重新添加默认值即可。迁移系统的一大好处是,它可以轻松地在 Django ORM 之外对数据库进行任意、可重复、可测试的更改。所以只需添加一个新的 RunSQL迁移操作:

operations = [
# Add SQL for both forward and reverse operations
migrations.RunSQL("ALTER TABLE app_mymodel ALTER COLUMN new_field SET DEFAULT 0;",
"ALTER TABLE app_mymodel ALTER COLUMN new_field DROP DEFAULT;")
]

您可以将其放入 new migration file 中或者直接编辑自动生成的。根据您的数据库及其对事务 DDL 的支持,操作顺序可能是也可能不是原子的。

关于mysql - 为什么 Django 在添加新列时删除 SQL DEFAULT 约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58077193/

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