123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- from operator import attrgetter
- from django.contrib.contenttypes.models import ContentType
- from django.db import models
- from django.db.models import Count
- from django.test import TestCase
- from .models import (
- Base,
- Child,
- Derived,
- Feature,
- Item,
- ItemAndSimpleItem,
- Leaf,
- Location,
- OneToOneItem,
- Proxy,
- ProxyRelated,
- RelatedItem,
- Request,
- ResolveThis,
- SimpleItem,
- SpecialFeature,
- )
- class DeferRegressionTest(TestCase):
- def test_basic(self):
-
-
- Item.objects.create(name="first", value=42)
- obj = Item.objects.only("name", "other_value").get(name="first")
-
-
- with self.assertNumQueries(0):
- self.assertEqual(obj.name, "first")
- self.assertEqual(obj.other_value, 0)
- with self.assertNumQueries(1):
- self.assertEqual(obj.value, 42)
- with self.assertNumQueries(1):
- self.assertEqual(obj.text, "xyzzy")
- with self.assertNumQueries(0):
- self.assertEqual(obj.text, "xyzzy")
-
-
- i = Item.objects.create(name="no I'm first", value=37)
- items = Item.objects.only("value").order_by("-value")
- self.assertEqual(items[0].name, "first")
- self.assertEqual(items[1].name, "no I'm first")
- RelatedItem.objects.create(item=i)
- r = RelatedItem.objects.defer("item").get()
- self.assertEqual(r.item_id, i.id)
- self.assertEqual(r.item, i)
-
-
- c1 = Child.objects.create(name="c1", value=42)
- c2 = Child.objects.create(name="c2", value=37)
- Leaf.objects.create(name="l1", child=c1, second_child=c2)
- obj = Leaf.objects.only("name", "child").select_related()[0]
- self.assertEqual(obj.child.name, "c1")
- self.assertQuerySetEqual(
- Leaf.objects.select_related().only("child__name", "second_child__name"),
- [
- "l1",
- ],
- attrgetter("name"),
- )
-
-
- ctype = ContentType.objects.get_for_model
- c1 = ctype(Item.objects.all()[0])
- c2 = ctype(Item.objects.defer("name")[0])
- c3 = ctype(Item.objects.only("name")[0])
- self.assertTrue(c1 is c2 is c3)
-
-
- results = Leaf.objects.only("name", "child", "second_child").select_related()
- self.assertEqual(results[0].child.name, "c1")
- self.assertEqual(results[0].second_child.name, "c2")
- results = Leaf.objects.only(
- "name", "child", "second_child", "child__name", "second_child__name"
- ).select_related()
- self.assertEqual(results[0].child.name, "c1")
- self.assertEqual(results[0].second_child.name, "c2")
-
- self.assertIsInstance(
- list(SimpleItem.objects.annotate(Count("feature")).defer("name")), list
- )
- self.assertIsInstance(
- list(SimpleItem.objects.annotate(Count("feature")).only("name")), list
- )
- def test_ticket_16409(self):
-
- self.assertIsInstance(
- list(SimpleItem.objects.annotate(Count("feature")).defer("name")), list
- )
- self.assertIsInstance(
- list(SimpleItem.objects.annotate(Count("feature")).only("name")), list
- )
- def test_ticket_23270(self):
- d = Derived.objects.create(text="foo", other_text="bar")
- with self.assertNumQueries(1):
- obj = Base.objects.select_related("derived").defer("text")[0]
- self.assertIsInstance(obj.derived, Derived)
- self.assertEqual("bar", obj.derived.other_text)
- self.assertNotIn("text", obj.__dict__)
- self.assertEqual(d.pk, obj.derived.base_ptr_id)
- def test_only_and_defer_usage_on_proxy_models(self):
-
- proxy = Proxy.objects.create(name="proxy", value=42)
- msg = "QuerySet.only() return bogus results with proxy models"
- dp = Proxy.objects.only("other_value").get(pk=proxy.pk)
- self.assertEqual(dp.name, proxy.name, msg=msg)
- self.assertEqual(dp.value, proxy.value, msg=msg)
-
- msg = "QuerySet.defer() return bogus results with proxy models"
- dp = Proxy.objects.defer("name", "text", "value").get(pk=proxy.pk)
- self.assertEqual(dp.name, proxy.name, msg=msg)
- self.assertEqual(dp.value, proxy.value, msg=msg)
- def test_resolve_columns(self):
- ResolveThis.objects.create(num=5.0, name="Foobar")
- qs = ResolveThis.objects.defer("num")
- self.assertEqual(1, qs.count())
- self.assertEqual("Foobar", qs[0].name)
- def test_reverse_one_to_one_relations(self):
-
-
- item = Item.objects.create(name="first", value=42)
- o2o = OneToOneItem.objects.create(item=item, name="second")
- self.assertEqual(len(Item.objects.defer("one_to_one_item__name")), 1)
- self.assertEqual(len(Item.objects.select_related("one_to_one_item")), 1)
- self.assertEqual(
- len(
- Item.objects.select_related("one_to_one_item").defer(
- "one_to_one_item__name"
- )
- ),
- 1,
- )
- self.assertEqual(
- len(Item.objects.select_related("one_to_one_item").defer("value")), 1
- )
-
-
- self.assertEqual(len(Item.objects.only("one_to_one_item")), 1)
- with self.assertNumQueries(1):
- i = Item.objects.select_related("one_to_one_item")[0]
- self.assertEqual(i.one_to_one_item.pk, o2o.pk)
- self.assertEqual(i.one_to_one_item.name, "second")
- with self.assertNumQueries(1):
- i = Item.objects.select_related("one_to_one_item").defer(
- "value", "one_to_one_item__name"
- )[0]
- self.assertEqual(i.one_to_one_item.pk, o2o.pk)
- self.assertEqual(i.name, "first")
- with self.assertNumQueries(1):
- self.assertEqual(i.one_to_one_item.name, "second")
- with self.assertNumQueries(1):
- self.assertEqual(i.value, 42)
- def test_defer_with_select_related(self):
- item1 = Item.objects.create(name="first", value=47)
- item2 = Item.objects.create(name="second", value=42)
- simple = SimpleItem.objects.create(name="simple", value="23")
- ItemAndSimpleItem.objects.create(item=item1, simple=simple)
- obj = ItemAndSimpleItem.objects.defer("item").select_related("simple").get()
- self.assertEqual(obj.item, item1)
- self.assertEqual(obj.item_id, item1.id)
- obj.item = item2
- obj.save()
- obj = ItemAndSimpleItem.objects.defer("item").select_related("simple").get()
- self.assertEqual(obj.item, item2)
- self.assertEqual(obj.item_id, item2.id)
- def test_proxy_model_defer_with_select_related(self):
-
- item = Item.objects.create(name="first", value=47)
- RelatedItem.objects.create(item=item)
-
- obj = ProxyRelated.objects.select_related().only("item__name")[0]
- with self.assertNumQueries(0):
- self.assertEqual(obj.item.name, "first")
- with self.assertNumQueries(1):
- self.assertEqual(obj.item.value, 47)
- def test_only_with_select_related(self):
-
- item = SimpleItem.objects.create(name="first", value=47)
- feature = Feature.objects.create(item=item)
- SpecialFeature.objects.create(feature=feature)
- qs = Feature.objects.only("item__name").select_related("item")
- self.assertEqual(len(qs), 1)
- qs = SpecialFeature.objects.only("feature__item__name").select_related(
- "feature__item"
- )
- self.assertEqual(len(qs), 1)
- def test_defer_annotate_select_related(self):
- location = Location.objects.create()
- Request.objects.create(location=location)
- self.assertIsInstance(
- list(
- Request.objects.annotate(Count("items"))
- .select_related("profile", "location")
- .only("profile", "location")
- ),
- list,
- )
- self.assertIsInstance(
- list(
- Request.objects.annotate(Count("items"))
- .select_related("profile", "location")
- .only("profile__profile1", "location__location1")
- ),
- list,
- )
- self.assertIsInstance(
- list(
- Request.objects.annotate(Count("items"))
- .select_related("profile", "location")
- .defer("request1", "request2", "request3", "request4")
- ),
- list,
- )
- def test_common_model_different_mask(self):
- child = Child.objects.create(name="Child", value=42)
- second_child = Child.objects.create(name="Second", value=64)
- Leaf.objects.create(child=child, second_child=second_child)
- with self.assertNumQueries(1):
- leaf = (
- Leaf.objects.select_related("child", "second_child")
- .defer("child__name", "second_child__value")
- .get()
- )
- self.assertEqual(leaf.child, child)
- self.assertEqual(leaf.second_child, second_child)
- self.assertEqual(leaf.child.get_deferred_fields(), {"name"})
- self.assertEqual(leaf.second_child.get_deferred_fields(), {"value"})
- with self.assertNumQueries(0):
- self.assertEqual(leaf.child.value, 42)
- self.assertEqual(leaf.second_child.name, "Second")
- with self.assertNumQueries(1):
- self.assertEqual(leaf.child.name, "Child")
- with self.assertNumQueries(1):
- self.assertEqual(leaf.second_child.value, 64)
- class DeferDeletionSignalsTests(TestCase):
- senders = [Item, Proxy]
- @classmethod
- def setUpTestData(cls):
- cls.item_pk = Item.objects.create(value=1).pk
- def setUp(self):
- self.pre_delete_senders = []
- self.post_delete_senders = []
- for sender in self.senders:
- models.signals.pre_delete.connect(self.pre_delete_receiver, sender)
- models.signals.post_delete.connect(self.post_delete_receiver, sender)
- def tearDown(self):
- for sender in self.senders:
- models.signals.pre_delete.disconnect(self.pre_delete_receiver, sender)
- models.signals.post_delete.disconnect(self.post_delete_receiver, sender)
- def pre_delete_receiver(self, sender, **kwargs):
- self.pre_delete_senders.append(sender)
- def post_delete_receiver(self, sender, **kwargs):
- self.post_delete_senders.append(sender)
- def test_delete_defered_model(self):
- Item.objects.only("value").get(pk=self.item_pk).delete()
- self.assertEqual(self.pre_delete_senders, [Item])
- self.assertEqual(self.post_delete_senders, [Item])
- def test_delete_defered_proxy_model(self):
- Proxy.objects.only("value").get(pk=self.item_pk).delete()
- self.assertEqual(self.pre_delete_senders, [Proxy])
- self.assertEqual(self.post_delete_senders, [Proxy])
|