psycopg2 のバックエンドとして PostgreSQL を使用していますが、奇妙なことに気付きました。私のセットアップは次のとおりです。
class ParentModel(models.Model):
field1 = models.IntegerField()
class ChildModel(ParentModel):
field2 = models.IntegerField(unique=True)
シェルから重複する field2 を使用して ChildModel オブジェクトを保存しようとすると、IntegrityError ではなく InternalError が返されますが、次のように transaction.commit_on_success ブロックで保存が行われた場合のみです。
with transaction.commit_on_success():
newObj = ChildModel(field1=5, field2=10) # Assume that a ChildModel with field2 == 10 exists
トランザクション ブロックの外では、予想どおり、IntegrityError が発生します。
ビューコード内で実行すると、セーブポイントを使用していても、失敗した更新に続いて常に InternalError が発生します。
try:
sid = transaction.savepoint()
newObj = ChildModel(field1=5, field2=10) # Assume that a ChildModel with field2 == 10 exists
transaction.savepoint_commit(sid)
except IntegrityError:
transaction.savepoint_rollback(sid)
except InternalError:
transaction.savepoint_rollback(sid)
... other stuff ... # raises InternalError on next database hit
セーブポイントを使用する代わりに、ブロックを使用して commit_on_success トランザクション内で実行すると、同じことが起こります。TransactionMiddleware をインストールしましたが、PostgreSQL を自動コミット モードで実行していません。
重複したオブジェクトが存在しないことを確認するだけで状況を回避できますが、Django トランザクションの理解で何が問題になっているのかを知りたいです。何を与える?