Loading django/db/models/query.py +3 −3 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ import warnings from django.conf import settings from django.core import exceptions from django.db import connections, router, transaction, IntegrityError from django.db import connections, router, transaction, DatabaseError from django.db.models.constants import LOOKUP_SEP from django.db.models.fields import AutoField from django.db.models.query_utils import (Q, select_related_descend, Loading Loading @@ -382,13 +382,13 @@ class QuerySet(object): obj.save(force_insert=True, using=self.db) transaction.savepoint_commit(sid, using=self.db) return obj, True except IntegrityError: except DatabaseError: transaction.savepoint_rollback(sid, using=self.db) exc_info = sys.exc_info() try: return self.get(**lookup), False except self.model.DoesNotExist: # Re-raise the IntegrityError with its original traceback. # Re-raise the DatabaseError with its original traceback. six.reraise(*exc_info) def _earliest_or_latest(self, field_name=None, direction="-"): Loading tests/get_or_create/tests.py +19 −1 Original line number Diff line number Diff line Loading @@ -2,14 +2,16 @@ from __future__ import absolute_import from datetime import date import traceback import warnings from django.db import IntegrityError from django.db import IntegrityError, DatabaseError from django.test import TestCase, TransactionTestCase from .models import Person, ManualPrimaryKeyTest, Profile, Tag, Thing class GetOrCreateTests(TestCase): def test_get_or_create(self): p = Person.objects.create( first_name='John', last_name='Lennon', birthday=date(1940, 10, 9) Loading Loading @@ -64,6 +66,22 @@ class GetOrCreateTests(TestCase): formatted_traceback = traceback.format_exc() self.assertIn('obj.save', formatted_traceback) def test_savepoint_rollback(self): # Regression test for #20463: the database connection should still be # usable after a DataError or ProgrammingError in .get_or_create(). try: # Hide warnings when broken data is saved with a warning (MySQL). with warnings.catch_warnings(): warnings.simplefilter('ignore') Person.objects.get_or_create( birthday=date(1970, 1, 1), defaults={'first_name': "\xff", 'last_name': "\xff"}) except DatabaseError: Person.objects.create( first_name="Bob", last_name="Ross", birthday=date(1950, 1, 1)) else: self.skipTest("This backend accepts broken utf-8.") class GetOrCreateTransactionTests(TransactionTestCase): Loading Loading
django/db/models/query.py +3 −3 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ import warnings from django.conf import settings from django.core import exceptions from django.db import connections, router, transaction, IntegrityError from django.db import connections, router, transaction, DatabaseError from django.db.models.constants import LOOKUP_SEP from django.db.models.fields import AutoField from django.db.models.query_utils import (Q, select_related_descend, Loading Loading @@ -382,13 +382,13 @@ class QuerySet(object): obj.save(force_insert=True, using=self.db) transaction.savepoint_commit(sid, using=self.db) return obj, True except IntegrityError: except DatabaseError: transaction.savepoint_rollback(sid, using=self.db) exc_info = sys.exc_info() try: return self.get(**lookup), False except self.model.DoesNotExist: # Re-raise the IntegrityError with its original traceback. # Re-raise the DatabaseError with its original traceback. six.reraise(*exc_info) def _earliest_or_latest(self, field_name=None, direction="-"): Loading
tests/get_or_create/tests.py +19 −1 Original line number Diff line number Diff line Loading @@ -2,14 +2,16 @@ from __future__ import absolute_import from datetime import date import traceback import warnings from django.db import IntegrityError from django.db import IntegrityError, DatabaseError from django.test import TestCase, TransactionTestCase from .models import Person, ManualPrimaryKeyTest, Profile, Tag, Thing class GetOrCreateTests(TestCase): def test_get_or_create(self): p = Person.objects.create( first_name='John', last_name='Lennon', birthday=date(1940, 10, 9) Loading Loading @@ -64,6 +66,22 @@ class GetOrCreateTests(TestCase): formatted_traceback = traceback.format_exc() self.assertIn('obj.save', formatted_traceback) def test_savepoint_rollback(self): # Regression test for #20463: the database connection should still be # usable after a DataError or ProgrammingError in .get_or_create(). try: # Hide warnings when broken data is saved with a warning (MySQL). with warnings.catch_warnings(): warnings.simplefilter('ignore') Person.objects.get_or_create( birthday=date(1970, 1, 1), defaults={'first_name': "\xff", 'last_name': "\xff"}) except DatabaseError: Person.objects.create( first_name="Bob", last_name="Ross", birthday=date(1950, 1, 1)) else: self.skipTest("This backend accepts broken utf-8.") class GetOrCreateTransactionTests(TransactionTestCase): Loading