2012-08-07 4 views
9

ho questo codice:Foo.objects.get (id = None) restituisce esempio Foo, a volte

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

... e, a volte, l'eccezione in qualche modo viene sollevato. Come potrebbe mai accadere?

Una volta ogni tanto, più volte al giorno, restituisce istanze di commenti apparentemente casuali. Di solito si comporta come previsto e restituisce Nessuno.

Questo è il campo ID della tabella Commento: id int(11) NOT NULL AUTO_INCREMENT quindi non è che sia annullabile. È una tabella InnoDB.

Come per Comment.all_objects, questa è la sua definizione: all_objects = Manager() ed è la prima riga di quella classe.

Siamo su Django 1.2.7.

Aggiornamento Aggiunto accesso all'eccezione per ottenere l'SQL generato quando viene sollevata l'eccezione. Eccolo:

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

Dove hai definito il parent_comment_id al 5 ° linea non riesco a trovarlo nel codice – zsong

+0

@sza è irrilevante -?. Mi sto chiedendo di come l'eccezione è in grado di essere sollevato, il che succede quando parent_comment_id è None – aehlke

+0

Ok. Ma se non lo hai ancora definito o assegnato con un valore precedente, è decisamente None. Puoi incollare il codice relativo all'assegnazione parent_comment_id? Grazie! – zsong

risposta

13

Questo comportamento è causato da profondamente strano (a modesto parere di questo codificatore) comportamento di MySQL , controllato by the SQL_AUTO_IS_NULL variable (che è 1 per impostazione predefinita in MySQL < 5.5.3):

Se questa variabile è impostata su 1, poi, dopo una dichiarazione che inserisce con successo un valore AUTO_INCREMENT generato automaticamente, è possibile trovare tale valore mediante l'emissione di una dichiarazione della forma seguente:

SELECT * FROM tbl_name WHERE auto_col IS NULL 

Se l'istruzione restituisce una riga, il valore restituito è lo stesso come se è stata richiamata la funzione LAST_INSERT_ID()

C'è a Django bug (closed: wontfix) describing similar confusion causati da questa "caratteristica", in cui un nucleo sviluppatore stati

Se non si desidera che il comportamento, è necessario configurare il database per fare la cosa giusta per le tue preferenze

La soluzione, quindi, è quello di disattivare l'opzione SQL_AUTO_IS_NULL del vostro database MySQL using the SET statement . È possibile farlo in settings.py con qualcosa di simile:

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

a più lungo termine, si può provare e drum-beat su the django-developers list per farli a riconsiderare their earlier position:

Per fortuna, il mio pensiero qui isn' t bruciando tutti i ponti. Se qualcuno ha voluto verificarlo, o lo usa per impostazione predefinita, può utilizzare le opzioni di inizializzazione del database tramite DATABASE_OPTIONS nelle impostazioni ... Entrambe "read_default_file" e "init_command" sono utili lì.

Non sto dicendo che questo dovrebbe essere "no, per sempre", ma in questo momento non sono convinto che valga la pena farlo. Equilibrato contro questo è il modo per far sapere alle persone di che potrebbe accadere ... shrug .. Potrei aggiungere qualcosa a databases.txt, per cominciare. Odio questo tipo di atto di bilanciamento. :-(

1

per escludere cose semplici:

  1. Potrebbe pubblicare il tuo modello di commento
  2. Potrebbe eseguire la seguente query contro il vostro DB

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

Il tuo codice logicamente dovrebbe funzionare escludendo qualcosa di fastidioso nel tuo codice modello, che mi porta a credere che debba essere correlato ai dati.

EDIT

un'altra idea, vedere che cosa ORM di Django sta interrogando (questo dovrebbe dirci cosa è in su):

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

La tua query restituisce 0 righe. Aggiunto l'SQL generato alla domanda. – aehlke