Django:迁移到 NullBooleanField 失败,IntegrityError“包含空值”

Posted

技术标签:

【中文标题】Django:迁移到 NullBooleanField 失败,IntegrityError“包含空值”【英文标题】:Django: migration to NullBooleanField fails with IntegrityError "contains null values" 【发布时间】:2015-06-06 05:01:48 【问题描述】:

我正在使用 Django 1.7 并尝试将名为 is_dispensing 的数据库字段从现有的 BooleanField 迁移到 NullBooleanField

我的迁移文件:

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

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('frontend', '0007_practice_is_dispensing'),
    ]

    operations = [
        migrations.AlterField(
            model_name='practice',
            name='is_dispensing',
            field=models.NullBooleanField(),
            preserve_default=True,
        ),
    ]

运行 manage.py migrate 失败并出现此错误:

django.db.utils.IntegrityError: column "is_dispensing" contains null values

我的模型文件中的字段:

is_dispensing = models.NullBooleanField(blank=True)

以前是:

is_dispensing = models.BooleanField(null=True, blank=True) 

当我添加它时,我被要求提供一个默认值,我将其设置为无。

我发现此消息令人困惑 - 我正在尝试将列类型迁移到 NullBooleanField,那么为什么它不能包含空值?这就是这种列类型的全部意义,不是吗? :)

更新:另一件令人困惑的事情:如果我进入 Postgres 并查看应该包含该列的表,它实际上根本没有 is_dispensing 列。

【问题讨论】:

我认为这里发生的事情是第一次迁移(创建 BooleanField(null=True, blank=True) 没有完全执行,因为 Django 1.7 不允许纯 BooleanField 字段具有空值。所以makemigrations 运行,但随后 migrate 失败。我……想?我仍然不明白当数据库中不存在该列时如何获得 IntegrityError blank=True 仅影响生成(例如在管理员中)。它不会影响实际的数据库表。尝试 manage.py migrate --fake。这将在您的迁移表中添加一个条目。您将需要检查数据库表以查看它们是否实际上有 NOT NULL 并手动更新它们。不是一个完美的解决方案,但我需要查看迁移文件以通过 django 迁移来修复它。 【参考方案1】:

项目表中 slug 和您的应用的非唯一组合可能会导致此错误。我通过手动编辑确保我所有的项目 slug 都是唯一的,从而修复了它。

您可以添加blank = true外键定义,删除所有迁移并再次运行迁移...

【讨论】:

以上是关于Django:迁移到 NullBooleanField 失败,IntegrityError“包含空值”的主要内容,如果未能解决你的问题,请参考以下文章

将迁移添加到源代码管理并合并 Django 中的冲突迁移

将密码字段迁移到 Django

将文件夹和文件结构从 django 1.3 迁移到 django 1.4 的最佳方法是啥?

Django:迁移到 NullBooleanField 失败,IntegrityError“包含空值”

无法将 Django 从 1.7 迁移到 1.8

Django 无法迁移到新数据库