PageRenderTime 21ms CodeModel.GetById 9ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/modeltests/defer/tests.py

https://code.google.com/p/mango-py/
Python | 137 lines | 98 code | 21 blank | 18 comment | 3 complexity | 98aa4d7feff93dad6c81d6d9506efba7 MD5 | raw file
  1from django.db.models.query_utils import DeferredAttribute
  2from django.test import TestCase
  3
  4from models import Secondary, Primary, Child, BigChild
  5
  6
  7class DeferTests(TestCase):
  8    def assert_delayed(self, obj, num):
  9        count = 0
 10        for field in obj._meta.fields:
 11            if isinstance(obj.__class__.__dict__.get(field.attname),
 12                DeferredAttribute):
 13                count += 1
 14        self.assertEqual(count, num)
 15
 16    def test_defer(self):
 17        # To all outward appearances, instances with deferred fields look the
 18        # same as normal instances when we examine attribute values. Therefore
 19        # we test for the number of deferred fields on returned instances (by
 20        # poking at the internals), as a way to observe what is going on.
 21
 22        s1 = Secondary.objects.create(first="x1", second="y1")
 23        p1 = Primary.objects.create(name="p1", value="xx", related=s1)
 24
 25        qs = Primary.objects.all()
 26
 27        self.assert_delayed(qs.defer("name")[0], 1)
 28        self.assert_delayed(qs.only("name")[0], 2)
 29        self.assert_delayed(qs.defer("related__first")[0], 0)
 30
 31        obj = qs.select_related().only("related__first")[0]
 32        self.assert_delayed(obj, 2)
 33
 34        self.assertEqual(obj.related_id, s1.pk)
 35
 36        self.assert_delayed(qs.defer("name").extra(select={"a": 1})[0], 1)
 37        self.assert_delayed(qs.extra(select={"a": 1}).defer("name")[0], 1)
 38        self.assert_delayed(qs.defer("name").defer("value")[0], 2)
 39        self.assert_delayed(qs.only("name").only("value")[0], 2)
 40        self.assert_delayed(qs.only("name").defer("value")[0], 2)
 41        self.assert_delayed(qs.only("name", "value").defer("value")[0], 2)
 42        self.assert_delayed(qs.defer("name").only("value")[0], 2)
 43
 44        obj = qs.only()[0]
 45        self.assert_delayed(qs.defer(None)[0], 0)
 46        self.assert_delayed(qs.only("name").defer(None)[0], 0)
 47
 48        # User values() won't defer anything (you get the full list of
 49        # dictionaries back), but it still works.
 50        self.assertEqual(qs.defer("name").values()[0], {
 51            "id": p1.id,
 52            "name": "p1",
 53            "value": "xx",
 54            "related_id": s1.id,
 55        })
 56        self.assertEqual(qs.only("name").values()[0], {
 57            "id": p1.id,
 58            "name": "p1",
 59            "value": "xx",
 60            "related_id": s1.id,
 61        })
 62
 63        # Using defer() and only() with get() is also valid.
 64        self.assert_delayed(qs.defer("name").get(pk=p1.pk), 1)
 65        self.assert_delayed(qs.only("name").get(pk=p1.pk), 2)
 66
 67        # DOES THIS WORK?
 68        self.assert_delayed(qs.only("name").select_related("related")[0], 1)
 69        self.assert_delayed(qs.defer("related").select_related("related")[0], 0)
 70
 71        # Saving models with deferred fields is possible (but inefficient,
 72        # since every field has to be retrieved first).
 73        obj = Primary.objects.defer("value").get(name="p1")
 74        obj.name = "a new name"
 75        obj.save()
 76        self.assertQuerysetEqual(
 77            Primary.objects.all(), [
 78                "a new name",
 79            ],
 80            lambda p: p.name
 81        )
 82
 83        # Regression for #10572 - A subclass with no extra fields can defer
 84        # fields from the base class
 85        Child.objects.create(name="c1", value="foo", related=s1)
 86        # You can defer a field on a baseclass when the subclass has no fields
 87        obj = Child.objects.defer("value").get(name="c1")
 88        self.assert_delayed(obj, 1)
 89        self.assertEqual(obj.name, "c1")
 90        self.assertEqual(obj.value, "foo")
 91        obj.name = "c2"
 92        obj.save()
 93
 94        # You can retrive a single column on a base class with no fields
 95        obj = Child.objects.only("name").get(name="c2")
 96        self.assert_delayed(obj, 3)
 97        self.assertEqual(obj.name, "c2")
 98        self.assertEqual(obj.value, "foo")
 99        obj.name = "cc"
100        obj.save()
101
102        BigChild.objects.create(name="b1", value="foo", related=s1, other="bar")
103        # You can defer a field on a baseclass
104        obj = BigChild.objects.defer("value").get(name="b1")
105        self.assert_delayed(obj, 1)
106        self.assertEqual(obj.name, "b1")
107        self.assertEqual(obj.value, "foo")
108        self.assertEqual(obj.other, "bar")
109        obj.name = "b2"
110        obj.save()
111
112        # You can defer a field on a subclass
113        obj = BigChild.objects.defer("other").get(name="b2")
114        self.assert_delayed(obj, 1)
115        self.assertEqual(obj.name, "b2")
116        self.assertEqual(obj.value, "foo")
117        self.assertEqual(obj.other, "bar")
118        obj.name = "b3"
119        obj.save()
120
121        # You can retrieve a single field on a baseclass
122        obj = BigChild.objects.only("name").get(name="b3")
123        self.assert_delayed(obj, 4)
124        self.assertEqual(obj.name, "b3")
125        self.assertEqual(obj.value, "foo")
126        self.assertEqual(obj.other, "bar")
127        obj.name = "b4"
128        obj.save()
129
130        # You can retrieve a single field on a baseclass
131        obj = BigChild.objects.only("other").get(name="b4")
132        self.assert_delayed(obj, 4)
133        self.assertEqual(obj.name, "b4")
134        self.assertEqual(obj.value, "foo")
135        self.assertEqual(obj.other, "bar")
136        obj.name = "bb"
137        obj.save()