IntegrityError:postgres 从转储恢复后,所有具有 ForeignKey 的模型/字段的“id”列中的空值

Posted

技术标签:

【中文标题】IntegrityError:postgres 从转储恢复后,所有具有 ForeignKey 的模型/字段的“id”列中的空值【英文标题】:IntegrityError: null value in column "id" for all models/fields with ForeignKey after postgres restore from dump 【发布时间】:2018-05-24 11:48:05 【问题描述】:

我在尝试从我拥有的本地 postgres 数据库的还原中使用 heroku postgres 数据存储时遇到问题。使用恢复的 postgres 数据库 Django 正常运行。它检索所有对象并使用它们的字段、主键等,没有任何问题。

但是在写入数据库时​​,无论型号如何,我都会遇到同样的错误。

psycopg2.IntegrityError:“id”列中的空值违反非空约束

当我重置 heroku 数据库并从空白页创建对象时,没有任何问题。但是如果我尝试在恢复的数据库上创建任何对象,我总是会得到这个null value in column "id" violates not-null constraint


这是尝试在 Django Admin 中创建基本模型时复制/粘贴的堆栈跟踪。我选择了这个模型示例,因为没有与创建它相关的额外代码。没有信号或任何东西。

Django 版本:2.0 Python 版本:3.6.3

追溯:

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/backends/utils.py” 在_执行 85. return self.cursor.execute(sql, params)

上述异常(“id”列中的空值违反了非空 约束细节:失败行包含(空,特殊类, 特级)。 ) 是以下异常的直接原因:

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/core/handlers/exception.py” 在内部 35. response = get_response(request)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/core/handlers/base.py” 在 _get_response 128. response = self.process_exception_by_middleware(e, request)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/core/handlers/base.py” 在 _get_response 126. response = Wrapped_callback(request, *callback_args, **callback_kwargs)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/contrib/admin/options.py” 在包装中 574. return self.admin_site.admin_view(view)(*args, **kwargs)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/utils/decorators.py” 在 _wrapped_view 142. response = view_func(request, *args, **kwargs)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/views/decorators/cache.py” 在 _wrapped_view_func 44. response = view_func(request, *args, **kwargs)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/contrib/admin/sites.py” 在内部 223. 返回视图(请求,*args,**kwargs)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/contrib/admin/options.py” 在 add_view 1553. return self.changeform_view(request, None, form_url, extra_context)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/utils/decorators.py” 在 _wrapper 中 62. return bound_func(*args, **kwargs)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/utils/decorators.py” 在 _wrapped_view 142. response = view_func(request, *args, **kwargs)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/utils/decorators.py” 在 bound_func 58. return func.get(self, type(self))(*args2, **kwargs2)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/contrib/admin/options.py” 在 changeform_view 1450. return self._changeform_view(request, object_id, form_url, extra_context)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/contrib/admin/options.py” 在_changeform_view 1490. self.save_model(request, new_object, form, not add)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/contrib/admin/options.py” 在 save_model 1026. obj.save()

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/models/base.py” 在保存 729. force_update=force_update, update_fields=update_fields)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/models/base.py” 在 save_base 759. 更新 = self._save_table(raw, cls, force_insert, force_update, using, update_fields)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/models/base.py” 在_save_table 842. 结果 = self._do_insert(cls._base_manager, using, fields, update_pk, raw)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/models/base.py” 在 _do_insert 880. 使用=使用,原始=原始)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/models/manager.py” 在 manager_method 中 82. return getattr(self.get_queryset(), name)(*args, **kwargs)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/models/query.py” 在_插入 1125. return query.get_compiler(using=using).execute_sql(return_id)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/models/sql/compiler.py” 在执行_sql 1280. cursor.execute(sql,参数)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/backends/utils.py” 在执行 100. return super().execute(sql, params)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/backends/utils.py” 在执行 68. return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/backends/utils.py” 在 _execute_with_wrappers 77. return executor(sql, params, many, context)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/backends/utils.py” 在_执行 85. return self.cursor.execute(sql, params)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/utils.py” 在退出 89. 从 exc_value 提高 dj_exc_value.with_traceback(traceback)

文件 “/app/.heroku/python/lib/python3.6/site-packages/django/db/backends/utils.py” 在_执行 85. return self.cursor.execute(sql, params)

异常类型:IntegrityError at /admin/fantasy/raceclass/add/ 异常值:“id”列中的空值违反非空值 约束细节:失败行包含(空,特殊类, 特殊类)。


来自堆栈跟踪的模型(请记住,每个模型都会发生此错误,而不仅仅是这个[非常基本的]模型。)

class RaceClass(models.Model):
    title = models.CharField(max_length=140)
    slug = models.SlugField(unique=True)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['title']

以下是我将本地数据恢复到 heroku 的方法:

我正在使用命令转储我的本地 Postgres 数据库(版本 10.0):

PGPASSWORD=mypassword pg_dump -Fc --no-acl --no-owner -h localhost -U myuser mydb > mydb.dump

然后上传到 AWS,并使用命令恢复到 Heroku 上的 Postgres 数据存储(版本 9.6.5):

heroku pg:backups:restore 'https://s3.amazonaws.com/me/items/3H0q/mydb.dump' DATABASE_URL

这些都直接来自 Heroku 文档:https://devcenter.heroku.com/articles/heroku-postgres-import-export


旁注:我在本地使用 10.0 版 Postgres,而 Heroku 数据存储是 9.6.5

【问题讨论】:

请您发布错误的完整堆栈跟踪,以及发生错误时运行的代码(对于您尝试保存的任何模型)以及相关的模型类。从这个角度来看,问题似乎不在于您的数据库还原,而在于您尝试写入数据库的内容。 @solarissmoke 添加了堆栈跟踪和模型代码。当问题发生在所有人身上时,我选择了我能找到的最基本的一个。希望你能帮忙! 【参考方案1】:

我很确定这是因为您正在从 Postgres 10 导出并导入 9。它并没有完全失败,但某些架构定义(在本例中为自动递增的 ID 字段)不正确进口的。

我能想到两个选择:

    尝试转储原始 SQL 而不是自定义格式:

    PGPASSWORD=mypassword pg_dump --no-acl --no-owner -h localhost -U myuser mydb > mydb.sql
    

    您不能使用 pg_restore 来加载它 - 您必须使用 psql 手动运行查询。像这样的东西应该可以工作:

    heroku pg:psql < mydb.sql
    

    这里需要注意的是,您首先需要清空现有数据库。

    如果这也失败了,那么您需要从要导入的同一主要版本的 Postgres 中导出。

【讨论】:

如果您没有在相应的模型上手动设置id = models.AutoField() 属性,这是100% 正确的。【参考方案2】:

关键错误是这样的:

我在本地使用 10.0 版 Postgres,Heroku 数据存储是 9.6.5

这是一个等待发生的问题。我会尝试在两者上使用相同的版本。至少相同的主要版本。

特别想到这两个是标准 SQL IDENTITY columns in Postgres 10 的引入,它旨在很大程度上取代串行列。你没有透露表定义,所以我只能猜测。 Postgres 10 中的 IDENTITY 功能不会转换回 Postgres 9.6,这可以很好地解释错误消息中违反 NULL 值的原因。

相关:

Auto increment table column

【讨论】:

【参考方案3】:

我最近遇到了同样的问题,这对我有用:

    创建新数据库

    使用 Django manage.py 转储我的数据库的数据,并在应用所有迁移后将其恢复到新数据库。

    python manage.py dumpdata --exclude auth.permission --exclude contenttypes --indent 2 > db.json

    恢复备份

    python manage.py loaddata db.json

【讨论】:

以上是关于IntegrityError:postgres 从转储恢复后,所有具有 ForeignKey 的模型/字段的“id”列中的空值的主要内容,如果未能解决你的问题,请参考以下文章

IntegrityError:重复键值违反唯一约束

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

错误:psycopg2.IntegrityError:“已修改”列在社交身份验证模块中包含空值?

django.db.utils.IntegrityError:列“venue_city”包含空值

Django IntegrityError:没有默认值

django.db.utils.IntegrityError:唯一约束失败:rango_category__new.slug