sql >> Base de Datos >  >> RDS >> PostgreSQL

IntegrityError:distinguir entre restricción única y violaciones no nulas

psycopg2 proporciona el SQLSTATE con la excepción de pgcode miembro, que le brinda información de error bastante detallada para hacer coincidir.

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 el Apéndice A:Códigos de error en el manual de PostgreSQL para conocer los significados del código. Tenga en cuenta que puede hacer coincidir aproximadamente los dos primeros caracteres para categorías amplias. En este caso puedo ver que SQLSTATE 42601 es syntax_error en el Syntax Error or Access Rule Violation categoría.

Los códigos que quieres son:

23505   unique_violation
23502   not_null_violation

así que podrías escribir:

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

Dicho esto, esta es una mala manera de hacer un upsert o merge . @pr0gg3d presumiblemente tiene razón al sugerir la forma correcta de hacerlo con Django; No hago Django, así que no puedo comentar sobre eso. Para obtener información general sobre upsert/merge, consulte el artículo de depesz sobre el tema.