Foo.objects.get(id=None) 有时会返回 Foo 实例



我有这个代码:

try:
    parent_comment = models.Comment.all_objects.get(id=parent_comment_id)
except models.Comment.DoesNotExist:
    parent_comment = None
if parent_comment is not None and parent_comment_id is None:
    raise Exception("WTF django/mysql")

。有时,异常会以某种方式引发。怎么会这样?

偶尔,每天几次,它会返回看似随机的 Comment 实例。通常它的行为符合预期并返回 None。

这是注释表的 id 字段:id int(11) NOT NULL AUTO_INCREMENT,因此它不是可为空的。这是一个InnoDB表。

至于Comment.all_objects,这是它的定义:all_objects = Manager(),它是该类的第一行。

我们在 Django 1.2.7 上。

更新向异常添加了日志记录,以获取引发异常时生成的 SQL。在这里:

SELECT `canvas_comment`.`id`, `canvas_comment`.`visibility`, `canvas_comment`.`parent_content_id`, `canvas_comment`.`parent_comment_id`, `canvas_comment`.`timestamp`, `canvas_comment`.`reply_content_id`, `canvas_comment`.`reply_text`, `canvas_comment`.`replied_comment_id`, `canvas_comment`.`category_id`, `canvas_comment`.`author_id`, `canvas_comment`.`title`, `canvas_comment`.`ip`, `canvas_comment`.`anonymous`, `canvas_comment`.`score`, `canvas_comment`.`judged`, `canvas_comment`.`ot_hidden` FROM `canvas_comment` WHERE `canvas_comment`.`id` IS NULL

这种行为是由非常奇怪的(以这个程序员的拙见)MySQL行为引起的,该行为由SQL_AUTO_IS_NULL变量控制(在MySQL <5.5.3中默认1):

如果此变量设置为 1,则在成功插入自动生成的 AUTO_INCREMENT 值的语句之后,可以通过发出以下形式的语句来查找该值:

SELECT * FROM tbl_name WHERE auto_col IS NULL

如果语句返回一行,则返回的值与调用 LAST_INSERT_ID() 函数时的值相同

有一个 Django 错误(关闭:wontfix)描述了由这个"功能"引起的类似混乱,其中核心开发人员声明

如果您不希望这种行为,则应将数据库配置为根据您的偏好执行正确的操作

然后,解决方案是使用 SET 语句禁用 MySQL 数据库的SQL_AUTO_IS_NULL选项。您可以在settings.py中执行此操作,如下所示:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        # ... your DB options
        'OPTIONS': {
            'init_command': 'SET SQL_AUTO_IS_NULL=0;'
        },
    }
}

从长远来看,你可以尝试在django开发者名单上敲打鼓,让他们重新考虑他们之前的立场:

幸运的是,我在这里的想法并没有烧毁任何桥梁。如果有人 想要测试一下,或者默认使用它,他们可以使用数据库 通过设置中的DATABASE_OPTIONS初始化选项...双 "read_default_file"和"init_command"在那里很有用。

我不是

说这应该是"不,永远",但现在我不是 确信这样做是值得的。与之平衡的是如何让 人们知道它可能会发生...耸耸肩..我可能会添加一些东西 数据库.txt,首先。我讨厌这种平衡行为。

排除简单的东西:

  1. 你能发布你的评论模型吗
  2. 您能否对数据库运行以下查询

SELECT COUNT(id) FROM <your_comment_table> WHERE id <= 0 OR id ='' OR id IS NULL

从逻辑上讲,你的代码应该可以工作,除非你的模型代码中有一些不稳定的东西,这让我相信它一定是与数据相关的。

编辑

另一个想法,看看 Django 的 ORM 正在查询什么(这应该告诉我们发生了什么):

parent_comment = models.Comment.all_objects.get(id=parent_comment_id)
raise Exception(parent_comment.query) # should display out the query thats being generated

相关内容

  • 没有找到相关文章

最新更新