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

2024-04-20 14:35:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这个代码:

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")

。。。有时候,这种例外会被提出。怎么会这样?在

偶尔,一天几次,它会返回看似随机的评论实例。通常它的行为与预期的一样,并且不返回任何结果。在

这是注释表的id字段:id int(11) NOT NULL AUTO_INCREMENT,所以它不是可以为null的。这是一个InnoDB表。在

至于注释。所有\u对象,这是它的定义:all_objects = Manager(),它是该类中的第一行。在

我们在Django 1.2.7上。在

更新 将日志记录添加到异常以获取引发异常时生成的SQL。这里是:

^{pr2}$

Tags: 代码noneidgetifobjectsismodels
2条回答

排除简单的事情:

  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

这种行为是由非常奇怪的(在这个程序员看来)MySQL行为引起的,它控制着by the ^{} variable(在MySQL<;5.5.3中默认为1):

If this variable is set to 1, then after a statement that successfully inserts an automatically generated AUTO_INCREMENT value, you can find that value by issuing a statement of the following form:

SELECT * FROM tbl_name WHERE auto_col IS NULL

If the statement returns a row, the value returned is the same as if you invoked the LAST_INSERT_ID() function

{a2中的一个特性是由^核心}引起的

If you don't want that behaviour, you should configure your database to do the right thing for your preferences

因此,解决方案是禁用MySQL数据库using the ^{} statementSQL_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

Fortunately, my thinking here isn't burning any bridges. If somebody wanted to test that out, or use it by default, they can use the database initialisation options via DATABASE_OPTIONS in settings ... Both "read_default_file" and "init_command" are useful there.

I'm not saying this should be "no, forever", but right now I'm not convinced it's worth doing this. Balanced against that is how to let people know that it might happen... shrug.. I might add something to databases.txt, for a start. I hate this sort of balancing act. :-(

相关问题 更多 >