summaryrefslogtreecommitdiff
path: root/tests/basic/tests.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/basic/tests.py')
-rw-r--r--tests/basic/tests.py60
1 files changed, 59 insertions, 1 deletions
diff --git a/tests/basic/tests.py b/tests/basic/tests.py
index 611944902a..2204989823 100644
--- a/tests/basic/tests.py
+++ b/tests/basic/tests.py
@@ -5,6 +5,7 @@ import threading
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.db import connections, DEFAULT_DB_ALIAS
+from django.db import DatabaseError
from django.db.models.fields import Field, FieldDoesNotExist
from django.db.models.manager import BaseManager
from django.db.models.query import QuerySet, EmptyQuerySet, ValuesListQuerySet, MAX_GET_RESULTS
@@ -12,7 +13,7 @@ from django.test import TestCase, TransactionTestCase, skipIfDBFeature, skipUnle
from django.utils import six
from django.utils.translation import ugettext_lazy
-from .models import Article, SelfRef
+from .models import Article, SelfRef, ArticleSelectOnSave
class ModelTest(TestCase):
@@ -806,3 +807,60 @@ class ManagerTest(TestCase):
sorted(BaseManager._get_queryset_methods(QuerySet).keys()),
sorted(self.QUERYSET_PROXY_METHODS),
)
+
+class SelectOnSaveTests(TestCase):
+ def test_select_on_save(self):
+ a1 = Article.objects.create(pub_date=datetime.now())
+ with self.assertNumQueries(1):
+ a1.save()
+ asos = ArticleSelectOnSave.objects.create(pub_date=datetime.now())
+ with self.assertNumQueries(2):
+ asos.save()
+ with self.assertNumQueries(1):
+ asos.save(force_update=True)
+ Article.objects.all().delete()
+ with self.assertRaises(DatabaseError):
+ with self.assertNumQueries(1):
+ asos.save(force_update=True)
+
+ def test_select_on_save_lying_update(self):
+ """
+ Test that select_on_save works correctly if the database
+ doesn't return correct information about matched rows from
+ UPDATE.
+ """
+ # Change the manager to not return "row matched" for update().
+ # We are going to change the Article's _base_manager class
+ # dynamically. This is a bit of a hack, but it seems hard to
+ # test this properly otherwise. Article's manager, because
+ # proxy models use their parent model's _base_manager.
+
+ orig_class = Article._base_manager.__class__
+
+ class FakeQuerySet(QuerySet):
+ # Make sure the _update method below is in fact called.
+ called = False
+
+ def _update(self, *args, **kwargs):
+ FakeQuerySet.called = True
+ super(FakeQuerySet, self)._update(*args, **kwargs)
+ return 0
+
+ class FakeManager(orig_class):
+ def get_queryset(self):
+ return FakeQuerySet(self.model)
+ try:
+ Article._base_manager.__class__ = FakeManager
+ asos = ArticleSelectOnSave.objects.create(pub_date=datetime.now())
+ with self.assertNumQueries(2):
+ asos.save()
+ self.assertTrue(FakeQuerySet.called)
+ # This is not wanted behaviour, but this is how Django has always
+ # behaved for databases that do not return correct information
+ # about matched rows for UPDATE.
+ with self.assertRaises(DatabaseError):
+ asos.save(force_update=True)
+ with self.assertRaises(DatabaseError):
+ asos.save(update_fields=['pub_date'])
+ finally:
+ Article._base_manager.__class__ = orig_class