はじめに
djangoで開発を行っている際にUniqueViolationのエラーを取得して例外処理を行うような処理を書く機会がありました。しかし、SQLAlchemyでのエラー取得のものしか見つからず、苦戦したのでdjangoで同じように困っている人の助けになればと思います。
そもそもUniqueViolationとは
UniqueViolationとは一意制約違反をあらわします。簡単にいうとDB内に重複した値を入れてはいけないことを示します。使用例として以下のテーブルのようなidに一意性があり、idを使って社員を管理している会社があるとします。idを参照すれば社員の名前と年齢が確認でき、社員を特定できます。それでは、新たに二人の社員のデータを追加するとしましょう。
id | name | age |
---|---|---|
001 | 田中 | 25 |
002 | 山本 | 30 |
003 | 菅谷 | 35 |
idが003の箇所で重複が発生していますね。これではidを参照して社員の特定ができないため、一意性が保たれていません。
id | name | age |
---|---|---|
001 | 田中 | 25 |
002 | 山本 | 30 |
003 | 菅谷 | 35 |
004 | 大川 | 30 |
003 | 竹之内 | 35 |
こういった現象を防ぐためにUniqueViolationを使用してidに重複したデータがないかを確認して一意性のあるものに保つことができます。
djangoのUniqueVaolationのエラー取得
さて本題に入ります。「直接UniqueVaolationをexceptで取得すればよいのでは…」と思うかもしれません。私もそう思いました。一意制約違反時IntegrityErrorを取得してしまっているようなので直接UniqueVaolationをexceptで取得することができませんでした。
from psycopg2.errors import UniqueViolation
try():
# データ操作
except UniqueVaolation:
# UniqueVaolation時の処理
IntegrityErrorのエラーの発生原因の一つとしてUniqueVaolationがあるので、IntegrityErrorのエラー原因を取得し、UniqueVaolationであるかを確認することでできるようです。実際に成功したものは以下の通りです。
__cause__を用いてエラーの原因を取得し、isinstanceでエラー原因にUniqueViolationが含まれているかを判定します。if文を用いて含まれているときにUniqueViolation時の処理を行うといった流れになります。
from psycopg2.errors import UniqueViolation
try():
# データ操作
except IntegrityError as e:
if isinstance(e.__cause__ , UniqueViolation)
#UniqueViolation時の処理
まとめ
djangoでUniqueViolationのエラーを取得する際は例外処理のIntegrityError内でエラーの原因がUniqueViolationであるかを調べるUniqueViolationのエラー取得を行えることがわかりました。
読みづらくわかりずらい文章となっておりますが、みなさんの手助けとなれば幸いです。