2012-08-07 12 views
9

tengo este código:Foo.objects.get (id = Ninguno) devuelve Foo ejemplo, a veces

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

... y, a veces, a excepción de alguna manera se levantada. ¿Cómo pudo suceder esto?

De vez en cuando, varias veces al día, devuelve instancias de comentario aparentemente al azar. Por lo general, se comporta como se esperaba y devuelve None.

Este es el campo id de la tabla comentario: id int(11) NOT NULL AUTO_INCREMENT por lo que no es que sea anulable. Es una tabla InnoDB.

En cuanto a Comment.all_objects, este es su definición: all_objects = Manager() y es la primera línea en esa clase.

Estamos en Django 1.2.7.

Actualización Agregué el registro a la excepción para obtener el SQL que se genera cuando se produce la excepción. Aquí está:

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

¿Dónde se define el parent_comment_id en la línea 5 que no lo encuentra en su código – zsong

+0

@sza es irrelevante -. Estoy preguntando acerca de cómo la excepción es capaz de ser elevada, que sucede cuando parent_comment_id es Ninguno. – aehlke

+0

Ok. Pero si no lo ha definido o asignado con un valor anterior, definitivamente no lo es. ¿Puede pegar el código que relaciona la asignación parent_comment_id? Gracias! – zsong

Respuesta

13

Este comportamiento se debe a profundamente extraño (en la humilde opinión de este codificador) el comportamiento de MySQL , controlado by the SQL_AUTO_IS_NULL variable (que es 1 por defecto en MySQL < 5.5.3):

Si esta variable se establece en 1, a continuación, después de una instrucción que inserta con éxito un valor AUTO_INCREMENT generado automáticamente, puede encontrar que el valor mediante la emisión de una declaración de la siguiente forma:

SELECT * FROM tbl_name WHERE auto_col IS NULL 

Si la instrucción devuelve una fila, el valor devuelto es el mismo que si se invoca la función LAST_INSERT_ID()

Hay a Django bug (closed: wontfix) describing similar confusion causada por esta "característica", en el que un desarrollador del núcleo estados

Si no desea que el comportamiento, debe configurar la base de datos para hacer lo correcto para sus preferencias

La solución, entonces, es desactivar la opción SQL_AUTO_IS_NULL de su base de datos MySQL using the SET statement . Puede hacer esto en settings.py con algo como:

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

A más largo plazo, se puede tratar de tambor-latido en the django-developers list para conseguir que se reconsideran their earlier position:

Afortunadamente, mi pensamiento aquí ISN' t quemando cualquier puente. Si alguien quisiera probarlo, o usarlo por defecto, puede usar las opciones de inicialización de la base de datos a través de DATABASE_OPTIONS en la configuración ... Ambos "read_default_file" e "init_command" son útiles allí.

No estoy diciendo que esto debería ser "no, para siempre", pero en este momento no estoy convencido de que vale la pena hacerlo. Equilibrado en contra de eso es cómo dejar que personas saben que podría suceder ... shrug .. Podría agregar algo a databases.txt, para empezar. Odio este tipo de acto de equilibrio. :-(

1

para descartar cosas simples:

  1. Podría publicar su modelo de comentario
  2. Podría ejecutar la siguiente consulta en contra de su base de datos

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

Su código lógicamente debería funcionar salvo algo inseguro en su modelo de código, lo que me lleva a creer que debe estar relacionado con los datos.

EDITAR

otra idea, ver lo ORM de Django está consultando (esto debería decirnos cuál está para arriba):

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

Su consulta arroja 0 filas. Agregó el SQL generado a la pregunta. – aehlke

Cuestiones relacionadas