PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

IntegrityError:distinguir entre restrições exclusivas e violações não nulas


psycopg2 fornece o SQLSTATE com exceção do pgcode member, que fornece informações de erro bastante refinadas para correspondência.
python3
>>> import psycopg2
>>> conn = psycopg2.connect("dbname=regress")
>>> curs = conn.cursor()
>>> try:
...     curs.execute("INVALID;")
... except Exception as ex:
...     xx = ex
>>> xx.pgcode
'42601'

Consulte o Apêndice A:Códigos de erro no manual do PostgreSQL para significados de código. Observe que você pode corresponder grosseiramente nos dois primeiros caracteres para categorias amplas. Neste caso, posso ver que SQLSTATE 42601 é syntax_error no Syntax Error or Access Rule Violation categoria.

Os códigos que você deseja são:
23505   unique_violation
23502   not_null_violation

então você poderia escrever:
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

Dito isto, esta é uma maneira ruim de fazer um upsert ou merge . @pr0gg3d provavelmente está certo em sugerir a maneira certa de fazer isso com o Django; Eu não faço Django, então não posso comentar sobre isso. Para informações gerais sobre upsert/merge veja o artigo do depesz sobre o tópico.