Fixed #16340 -- Made `get_or_create()` re-raise any `IntegrityError` with its original traceback. Thanks to d0ugal and Jonas Obrist.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17333 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Julien Phalip 2012-01-02 21:30:47 +00:00
parent fc9e0606d5
commit 31b1cbc623
2 changed files with 16 additions and 1 deletions

View File

@ -4,6 +4,7 @@ The main QuerySet implementation. This provides the public API for the ORM.
import copy import copy
import itertools import itertools
import sys
from django.db import connections, router, transaction, IntegrityError from django.db import connections, router, transaction, IntegrityError
from django.db.models.fields import AutoField from django.db.models.fields import AutoField
@ -450,10 +451,12 @@ class QuerySet(object):
return obj, True return obj, True
except IntegrityError, e: except IntegrityError, e:
transaction.savepoint_rollback(sid, using=self.db) transaction.savepoint_rollback(sid, using=self.db)
exc_info = sys.exc_info()
try: try:
return self.get(**lookup), False return self.get(**lookup), False
except self.model.DoesNotExist: except self.model.DoesNotExist:
raise e # Re-raise the IntegrityError with its original traceback.
raise exc_info[1], None, exc_info[2]
def latest(self, field_name=None): def latest(self, field_name=None):
""" """

View File

@ -1,6 +1,7 @@
from __future__ import absolute_import from __future__ import absolute_import
from datetime import date from datetime import date
import traceback
from django.db import IntegrityError from django.db import IntegrityError
from django.test import TestCase from django.test import TestCase
@ -52,3 +53,14 @@ class GetOrCreateTests(TestCase):
ManualPrimaryKeyTest.objects.get_or_create, id=1, data="Different" ManualPrimaryKeyTest.objects.get_or_create, id=1, data="Different"
) )
self.assertEqual(ManualPrimaryKeyTest.objects.get(id=1).data, "Original") self.assertEqual(ManualPrimaryKeyTest.objects.get(id=1).data, "Original")
# get_or_create should raise IntegrityErrors with the full traceback.
# This is tested by checking that a known method call is in the traceback.
# We cannot use assertRaises/assertRaises here because we need to inspect
# the actual traceback. Refs #16340.
try:
ManualPrimaryKeyTest.objects.get_or_create(id=1, data="Different")
except IntegrityError, e:
formatted_traceback = traceback.format_exc()
self.assertIn('obj.save', formatted_traceback)