parts/django/tests/regressiontests/defer_regress/tests.py
changeset 307 c6bca38c1cbf
equal deleted inserted replaced
306:5ff1fc726848 307:c6bca38c1cbf
       
     1 from operator import attrgetter
       
     2 
       
     3 from django.conf import settings
       
     4 from django.contrib.contenttypes.models import ContentType
       
     5 from django.contrib.sessions.backends.db import SessionStore
       
     6 from django.db import connection
       
     7 from django.db.models.loading import cache
       
     8 from django.test import TestCase
       
     9 
       
    10 from models import ResolveThis, Item, RelatedItem, Child, Leaf
       
    11 
       
    12 
       
    13 class DeferRegressionTest(TestCase):
       
    14     def assert_num_queries(self, n, func, *args, **kwargs):
       
    15         old_DEBUG = settings.DEBUG
       
    16         settings.DEBUG = True
       
    17         starting_queries = len(connection.queries)
       
    18         try:
       
    19             func(*args, **kwargs)
       
    20         finally:
       
    21             settings.DEBUG = old_DEBUG
       
    22         self.assertEqual(starting_queries + n, len(connection.queries))
       
    23 
       
    24     def test_basic(self):
       
    25         # Deferred fields should really be deferred and not accidentally use
       
    26         # the field's default value just because they aren't passed to __init__
       
    27 
       
    28         Item.objects.create(name="first", value=42)
       
    29         obj = Item.objects.only("name", "other_value").get(name="first")
       
    30         # Accessing "name" doesn't trigger a new database query. Accessing
       
    31         # "value" or "text" should.
       
    32         def test():
       
    33             self.assertEqual(obj.name, "first")
       
    34             self.assertEqual(obj.other_value, 0)
       
    35         self.assert_num_queries(0, test)
       
    36 
       
    37         def test():
       
    38             self.assertEqual(obj.value, 42)
       
    39         self.assert_num_queries(1, test)
       
    40 
       
    41         def test():
       
    42             self.assertEqual(obj.text, "xyzzy")
       
    43         self.assert_num_queries(1, test)
       
    44 
       
    45         def test():
       
    46             self.assertEqual(obj.text, "xyzzy")
       
    47         self.assert_num_queries(0, test)
       
    48 
       
    49         # Regression test for #10695. Make sure different instances don't
       
    50         # inadvertently share data in the deferred descriptor objects.
       
    51         i = Item.objects.create(name="no I'm first", value=37)
       
    52         items = Item.objects.only("value").order_by("-value")
       
    53         self.assertEqual(items[0].name, "first")
       
    54         self.assertEqual(items[1].name, "no I'm first")
       
    55 
       
    56         RelatedItem.objects.create(item=i)
       
    57         r = RelatedItem.objects.defer("item").get()
       
    58         self.assertEqual(r.item_id, i.id)
       
    59         self.assertEqual(r.item, i)
       
    60 
       
    61         # Some further checks for select_related() and inherited model
       
    62         # behaviour (regression for #10710).
       
    63         c1 = Child.objects.create(name="c1", value=42)
       
    64         c2 = Child.objects.create(name="c2", value=37)
       
    65         Leaf.objects.create(name="l1", child=c1, second_child=c2)
       
    66 
       
    67         obj = Leaf.objects.only("name", "child").select_related()[0]
       
    68         self.assertEqual(obj.child.name, "c1")
       
    69 
       
    70         self.assertQuerysetEqual(
       
    71             Leaf.objects.select_related().only("child__name", "second_child__name"), [
       
    72                 "l1",
       
    73             ],
       
    74             attrgetter("name")
       
    75         )
       
    76 
       
    77         # Models instances with deferred fields should still return the same
       
    78         # content types as their non-deferred versions (bug #10738).
       
    79         ctype = ContentType.objects.get_for_model
       
    80         c1 = ctype(Item.objects.all()[0])
       
    81         c2 = ctype(Item.objects.defer("name")[0])
       
    82         c3 = ctype(Item.objects.only("name")[0])
       
    83         self.assertTrue(c1 is c2 is c3)
       
    84 
       
    85         # Regression for #10733 - only() can be used on a model with two
       
    86         # foreign keys.
       
    87         results = Leaf.objects.only("name", "child", "second_child").select_related()
       
    88         self.assertEqual(results[0].child.name, "c1")
       
    89         self.assertEqual(results[0].second_child.name, "c2")
       
    90 
       
    91         results = Leaf.objects.only("name", "child", "second_child", "child__name", "second_child__name").select_related()
       
    92         self.assertEqual(results[0].child.name, "c1")
       
    93         self.assertEqual(results[0].second_child.name, "c2")
       
    94 
       
    95         # Test for #12163 - Pickling error saving session with unsaved model
       
    96         # instances.
       
    97         SESSION_KEY = '2b1189a188b44ad18c35e1baac6ceead'
       
    98 
       
    99         item = Item()
       
   100         item._deferred = False
       
   101         s = SessionStore(SESSION_KEY)
       
   102         s.clear()
       
   103         s["item"] = item
       
   104         s.save()
       
   105 
       
   106         s = SessionStore(SESSION_KEY)
       
   107         s.modified = True
       
   108         s.save()
       
   109 
       
   110         i2 = s["item"]
       
   111         self.assertFalse(i2._deferred)
       
   112 
       
   113         # Regression for #11936 - loading.get_models should not return deferred
       
   114         # models by default.
       
   115         klasses = sorted(
       
   116             cache.get_models(cache.get_app("defer_regress")),
       
   117             key=lambda klass: klass.__name__
       
   118         )
       
   119         self.assertEqual(
       
   120             klasses, [
       
   121                 Child,
       
   122                 Item,
       
   123                 Leaf,
       
   124                 RelatedItem,
       
   125                 ResolveThis,
       
   126             ]
       
   127         )
       
   128 
       
   129         klasses = sorted(
       
   130             map(
       
   131                 attrgetter("__name__"),
       
   132                 cache.get_models(
       
   133                     cache.get_app("defer_regress"), include_deferred=True
       
   134                 ),
       
   135             )
       
   136         )
       
   137         self.assertEqual(
       
   138             klasses, [
       
   139                 "Child",
       
   140                 "Child_Deferred_value",
       
   141                 "Item",
       
   142                 "Item_Deferred_name",
       
   143                 "Item_Deferred_name_other_value_text",
       
   144                 "Item_Deferred_name_other_value_value",
       
   145                 "Item_Deferred_other_value_text_value",
       
   146                 "Item_Deferred_text_value",
       
   147                 "Leaf",
       
   148                 "Leaf_Deferred_child_id_second_child_id_value",
       
   149                 "Leaf_Deferred_name_value",
       
   150                 "Leaf_Deferred_second_child_value",
       
   151                 "Leaf_Deferred_value",
       
   152                 "RelatedItem",
       
   153                 "RelatedItem_Deferred_",
       
   154                 "RelatedItem_Deferred_item_id",
       
   155                 "ResolveThis",
       
   156             ]
       
   157         )
       
   158 
       
   159     def test_resolve_columns(self):
       
   160         rt = ResolveThis.objects.create(num=5.0, name='Foobar')
       
   161         qs = ResolveThis.objects.defer('num')
       
   162         self.assertEqual(1, qs.count())
       
   163         self.assertEqual('Foobar', qs[0].name)