From 31b1cbc623c246570e7301c0334df938d840638f Mon Sep 17 00:00:00 2001
From: Julien Phalip <jphalip@gmail.com>
Date: Mon, 2 Jan 2012 21:30:47 +0000
Subject: [PATCH] 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
---
 django/db/models/query.py               |  5 ++++-
 tests/modeltests/get_or_create/tests.py | 12 ++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/django/db/models/query.py b/django/db/models/query.py
index fd531dd6d0..41c24c7a58 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -4,6 +4,7 @@ The main QuerySet implementation. This provides the public API for the ORM.
 
 import copy
 import itertools
+import sys
 
 from django.db import connections, router, transaction, IntegrityError
 from django.db.models.fields import AutoField
@@ -450,10 +451,12 @@ class QuerySet(object):
                 return obj, True
             except IntegrityError, e:
                 transaction.savepoint_rollback(sid, using=self.db)
+                exc_info = sys.exc_info()
                 try:
                     return self.get(**lookup), False
                 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):
         """
diff --git a/tests/modeltests/get_or_create/tests.py b/tests/modeltests/get_or_create/tests.py
index 4cf44507c8..f98f0e63d8 100644
--- a/tests/modeltests/get_or_create/tests.py
+++ b/tests/modeltests/get_or_create/tests.py
@@ -1,6 +1,7 @@
 from __future__ import absolute_import
 
 from datetime import date
+import traceback
 
 from django.db import IntegrityError
 from django.test import TestCase
@@ -52,3 +53,14 @@ class GetOrCreateTests(TestCase):
             ManualPrimaryKeyTest.objects.get_or_create, id=1, data="Different"
         )
         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)
+