我有这段代码:
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")
...有时,异常会以某种方式被提出。怎么会发生这种情况?
偶尔,一天几次,它会返回看似随机的评论实例。通常它按预期运行并返回None。
这是Comment表的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
答案 0 :(得分:13)
这种行为是由于奇怪的(在这个程序员的拙见)MySQL行为,受控by the SQL_AUTO_IS_NULL
variable(默认情况下1
在MySQL< 5.5.3中)引起的:
如果此变量设置为1,则在成功插入自动生成的AUTO_INCREMENT值的语句之后,您可以通过发出以下格式的语句来查找该值:
SELECT * FROM tbl_name WHERE auto_col IS NULL
如果语句返回一行,则返回的值与调用LAST_INSERT_ID()函数时的值相同
此“功能”导致a Django bug (closed: wontfix) describing similar confusion,其中核心开发人员声明
如果您不想要这种行为,则应将数据库配置为针对您的偏好做正确的事情
然后,解决方案是禁用MySQL数据库using the SET
statement的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;'
},
}
}
从长远来看,您可以尝试在the django-developers list上试拍,让他们重新考虑their earlier position:
幸运的是,我在这里的想法并没有烧掉任何桥梁。如果有人 想要测试它,或者默认使用它,他们可以使用数据库 通过设置中的DATABASE_OPTIONS初始化选项...两者 “read_default_file”和“init_command”在那里很有用。
我不是说这应该是“不,永远”,但现在我不是 确信这样做是值得的。平衡与此是如何让 人们知道它可能会发生...... 耸肩 ..我可能会添加一些内容 databases.txt,一个开始。我讨厌这种平衡行为。 : - (
答案 1 :(得分:1)
排除简单的事情:
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