2015-01-01 8 views
11

Come faccio specificamente prendere un vincolo UNIQUE fallito 404 nel codice seguente, so che devo aggiungere qualcosa in (qui?) Sezionecome si fa prendere un 'vincolo UNIQUE fallito' 404 in Django

try: 
    q = AnswerModel(user=user, yes_question=question_model) 
    q.save() 
except (here?): 
    return HttpResponseRedirect('/user/already_exists') 
+0

Hai provato * non * a prenderlo in modo da sapere cosa sia in realtà? –

+0

errrrr ovviamente, ora voglio catturare l'errore di vincolo univoco in modo da poter dire all'utente già risposto –

+0

Ok, quindi dato che sai di cosa si tratta, inseriscilo nella clausola 'except'. –

risposta

18
from django.db import IntegrityError 

except IntegrityError: 

Questo è quello che ti serve.

edito per @mbrochh:

from django.db import IntegrityError 

except IntegrityError as e: 
    if 'unique constraint' in e.message: # or e.args[0] from Django 1.10 
     #do something 

Sì, si può essere più precisi, ma nel caso in questione UNIQUE failed è altamente probabile.

+0

Questo non è sufficiente perché cattura di più dei soli vincoli UNIQUE. – mbrochh

+0

Ho modificato la mia risposta per voi. – torm

+0

Questa è ancora una brutta soluzione perché non sappiamo se quei messaggi cambieranno mai. Il controllo del codice di errore sarebbe un modo migliore. – mbrochh

0

In genere il principio "chiedi perdono" è una buona pratica di programmazione, ma in questo caso speciale non lo consiglierei.

L'eccezione che stai cercando è IntegrityError. Potresti averlo capito facilmente semplicemente rimuovendo il blocco try-catch e forzando quell'eccezione. Il traceback mostra la classe di eccezione.

Il problema è che ci sono diversi tipi di errori di integrità, quindi all'interno del vostro blocco try-catch si dovrà verificare la presenza di qualcosa di simile if ex.pgcode == 23505 per vedere se questo è in realtà un errore di vincolo UNIQUE. Questo è stato risposto prima qui: IntegrityError: distinguish between unique constraint and not null violations

c'è di peggio: Ogni ORM ha diversi codici di errore, il nome del campo non sarà pgcode ma qualcosa d'altro e alcuni ORM non gettare i vincoli UNIQUE a tutti. Quindi, se stai costruendo un'app riutilizzabile o se stai utilizzando un ORM che fa schifo (come MySQL) o se non sei sicuro se cambierai il database del tuo progetto in un determinato momento, non dovresti farlo!

Il modo migliore è semplicemente rimuovere il blocco try-catch e verificare se l'oggetto è già nel database prima di salvare.

Non so quale campo sia UNICO nel tuo caso, quindi presumo solo che sia il campo user. Il tuo codice sarebbe simile a questa:

answers = AnswerModel.objects.filter(user=user) 
if answers: 
    return HttpResponseRedirect('/user/already_exists') 
obj = AnswerModel.objects.create(user=user, yes_question=question_model) 
... 

Se avete a che fare con un vincolo unico combinato, la prima linea sarebbe questo:

answers = AnswerModel.objects.filter(user=user, yes_question=question_model) 
2

IMHO, mi sento di raccomandare a risolvere questa situazione da get_or_create().

new_obj, created = AnswerModel.objects.get_or_create(user=user, yes_question=question_model) 
if created: 
    do_something_for_new_object(new_obj) 
else: 
    logging.error("Duplicated item.") 
    return
Problemi correlati