python - IntegrityError 中缺少表名(Django ORM)

标签 python django postgresql django-orm

我在 Django 的 IntegrityError 中缺少表名:

Traceback (most recent call last):
...
    return self.cursor.execute(sql, params)
  File ".../django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File ".../django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
IntegrityError: null value in column "manager_slug" violates not-null constraint
DETAIL:  Failing row contains (17485, null, 2017-10-10 09:32:19, , 306).

有没有办法查看 INSERT/UPDATE 正在访问哪个表?

我们使用 PostgreSQL 9.6。

这是一个一般性问题:如何获得更好的错误信息?

这不是关于这个特定专栏的问题。很快就找到了相关的表格和专栏。但我想改进来 self 们 CI 系统的错误消息。下次我想立即看到表名。

我知道,如果我在软件开发过程中看到此错误,我可以使用调试器轻松揭示缺失的信息。但在我的例子中,这发生在生产中,我只有上面的堆栈跟踪。

最佳答案

此回溯中的异常消息是来自数据库驱动程序的原始消息。如果有任何内容被谷歌搜索、报告等,了解这一点和回溯很有用。

所有后端的异常类都是相同的 django.db.utils.IntegrityError,但消息或参数取决于后端:

  • postgres:“manager_slug”列中的空值违反了非空约束\n DETAILS...\n
  • mysql . . : (1048, "列 'manager_slug' 不能为 null")
  • sqlite3 。 : NOT NULL 约束失败:appname_modelname.manager_slug

表名仅在 sqlite3 后端可见。一些后端仅使用异常的字符串参数,但 mysql 使用两个参数:数字错误代码和消息。 (我愿意接受这是一个一般性问题,不仅是 PostgreSQL。)一些后端的作者希望应用程序的作者直接或从 SQL 知道表名,但对于一般的 ORM 包来说并非如此。即使在技术上可以做到完美,也没有更好的和普遍接受的方式来扩展消息。

开发调试简单:

  • 在开发中的 DEBUG 模式下可以使用许多附加信息(最后一帧中的“SQL”或“myobj.save()”等行中的对象的类名)
  • python manage.py test --debug-sql:“打印失败时记录的 SQL 查询。”
  • 使用 sqlite3 开发/测试中的相同错误更易于阅读。

...但您可能要求在生产中出现运行时错误。

我猜你在一个如此笼统的问题中可能的意图,你可能对哪个方向感兴趣。

A) traceback 中最重要的信息通常是许多行之上的几行".../django/db/...”。这对古鲁来说是非常容易的。如果代码不像 Django 管理站点那样动态和通用,则很有可能使用它,其中 myobj.save() 调用附近的代码(父框架中都不包含)不包含显式模型名称。示例:

# skip some initial universal code in ".../django/..."
...
# our apps start to be interesting... (maybe other installed app)
...
# START HERE: Open this line in the editor. If the function is universal, jump to the previous.
File ".../me/app/...py", line 47, in my...
  my_obj.save()
# skip many stack frames .../django/db/... below
File ".../django/db/models/base.py", line 734, in save
  # self.save_base(...    # this line 733 is not visible
      force_update=force_update, update_fields=update_fields)
...
# interesting only sql and params, but not visible in production
File ".../django/db/backends/utils.py", line 64, in execute
  return self.cursor.execute(sql, params)
IntegrityError (or DataError similarly)...

B) 通过模型的共同祖先获取信息

class ...(models.Model):
    def save(self, *args, **wkargs):
        try:
            super(..., self).save(*args, **wkargs)
        except django.db.utils.IntegrityError as exc:
            new_message = 'table {}'.format(self._meta.db_table)
            exc.extra_info = new_message
            # this is less compatible, but it doesn't require additional reading support
            # exc.args = exc.args + (new_message,)
            reraise

这可能会使多重继承的调试复杂化。

C) 在 Django db 中的实现 会更好,但我无法想象它会被接受并且在出现问题后不会恢复。

关于python - IntegrityError 中缺少表名(Django ORM),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46661147/

相关文章:

python - TensorFlow,如何查看 'blob' 内部,通过 CNN 响应

python - Celery WorkerLostError Worker 过早退出 : signal 6 (SIGABRT)

DJango:单个项目中的应用程序的多个实例

sql - 如何从数据库中选择重叠值对

Python:创建网络的最佳方法?

python - 这段代码中 self[identifier] = some_value 做了什么?

python - 如何监控 django-piston API 调用,甚至是错误的调用

python - "Unsupported hash type"错误 w/Python 2.6.5 和 django 框架

postgresql - Postgres Docker 镜像未使用自定义名称创建数据库

python - 哪个高效,使用 sql 连接查询,还是使用 pandas 合并查询?