Initially I thought being as specific as possible is the best way to go about it:
from django.db import IntegrityError
from psycopg2.errorcodes import UNIQUE_VIOLATION
try:
m = Model.objects.create(value=m2.old_value)
except IntegrityError as e:
if e.__cause__.pgcode != UNIQUE_VIOLATION:
raise
m = Model.objects.get(value=m2.old_value)
However later I ran into the answer that says:
SQLAlchemy is an abstraction library and if it were to raise exceptions specific to the underlying dpapi adapter, it would significantly reduce the portability of code written within it. ... However, unless your error handling is very specific to the type raised by the dbapi layer, I'd suggest that inspecting the underlying type might be unnecessary as the SQLAlchemy exception that is raised will provide enough runtime information to do what you have to do.
django.db.IntegrityError
is supposedly raised in the following cases:
INTEGRITY_CONSTRAINT_VIOLATION = '23000'
RESTRICT_VIOLATION = '23001'
NOT_NULL_VIOLATION = '23502'
FOREIGN_KEY_VIOLATION = '23503'
UNIQUE_VIOLATION = '23505'
CHECK_VIOLATION = '23514'
EXCLUSION_VIOLATION = '23P01'
I'm not sure under which circumstances these particular errors occur, but the general rule is, "don't ignore exceptions." And if I choose:
try:
m = Model.objects.create(value=m2.old_value)
except IntegrityError as e:
m = Model.objects.get(value=m2.old_value)
It sounds like I might ignore an exception I didn't mean to ignore. What would you suggest?