PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

IntegrityError:distingue tra vincolo univoco e violazioni non nulle

psycopg2 fornisce SQLSTATE con l'eccezione di pgcode membro, che fornisce informazioni sull'errore abbastanza dettagliate su cui eseguire la corrispondenza.

python3
>>> import psycopg2
>>> conn = psycopg2.connect("dbname=regress")
>>> curs = conn.cursor()
>>> try:
...     curs.execute("INVALID;")
... except Exception as ex:
...     xx = ex
>>> xx.pgcode
'42601'

Vedi Appendice A:Codici di errore nel manuale di PostgreSQL per i significati del codice. Nota che puoi abbinare grossolanamente i primi due caratteri per categorie ampie. In questo caso posso vedere che SQLSTATE 42601 è syntax_error in Syntax Error or Access Rule Violation categoria.

I codici che desideri sono:

23505   unique_violation
23502   not_null_violation

quindi potresti scrivere:

try:
    principal = cls.objects.create(
        user_id=user.id,
        email=user.email,
        path='something'
    )
except IntegrityError as ex:
    if ex.pgcode == '23505':
        principal = cls.objects.get(
            user_id=user.id,
            email=user.email
        )
    else:
        raise

Detto questo, questo è un brutto modo per fare un upsert o merge . @pr0gg3d presumibilmente ha ragione nel suggerire il modo giusto per farlo con Django; Non faccio Django, quindi non posso commentare quel bit. Per informazioni generali su upsert/merge, vedere l'articolo di depesz sull'argomento.