PageRenderTime 31ms CodeModel.GetById 21ms app.highlight 7ms RepoModel.GetById 2ms app.codeStats 0ms

/tests/modeltests/select_related/tests.py

https://code.google.com/p/mango-py/
Python | 168 lines | 152 code | 7 blank | 9 comment | 4 complexity | 68b7706010bc0f9e463ce9b0e62d1777 MD5 | raw file
  1from django.test import TestCase
  2
  3from models import Domain, Kingdom, Phylum, Klass, Order, Family, Genus, Species
  4
  5class SelectRelatedTests(TestCase):
  6
  7    def create_tree(self, stringtree):
  8        """
  9        Helper to create a complete tree.
 10        """
 11        names = stringtree.split()
 12        models = [Domain, Kingdom, Phylum, Klass, Order, Family, Genus, Species]
 13        assert len(names) == len(models), (names, models)
 14
 15        parent = None
 16        for name, model in zip(names, models):
 17            try:
 18                obj = model.objects.get(name=name)
 19            except model.DoesNotExist:
 20                obj = model(name=name)
 21            if parent:
 22                setattr(obj, parent.__class__.__name__.lower(), parent)
 23            obj.save()
 24            parent = obj
 25
 26    def create_base_data(self):
 27        self.create_tree("Eukaryota Animalia Anthropoda Insecta Diptera Drosophilidae Drosophila melanogaster")
 28        self.create_tree("Eukaryota Animalia Chordata Mammalia Primates Hominidae Homo sapiens")
 29        self.create_tree("Eukaryota Plantae Magnoliophyta Magnoliopsida Fabales Fabaceae Pisum sativum")
 30        self.create_tree("Eukaryota Fungi Basidiomycota Homobasidiomycatae Agaricales Amanitacae Amanita muscaria")
 31
 32    def setUp(self):
 33        # The test runner sets settings.DEBUG to False, but we want to gather
 34        # queries so we'll set it to True here and reset it at the end of the
 35        # test case.
 36        self.create_base_data()
 37
 38    def test_access_fks_without_select_related(self):
 39        """
 40        Normally, accessing FKs doesn't fill in related objects
 41        """
 42        def test():
 43            fly = Species.objects.get(name="melanogaster")
 44            domain = fly.genus.family.order.klass.phylum.kingdom.domain
 45            self.assertEqual(domain.name, 'Eukaryota')
 46        self.assertNumQueries(8, test)
 47
 48    def test_access_fks_with_select_related(self):
 49        """
 50        A select_related() call will fill in those related objects without any
 51        extra queries
 52        """
 53        def test():
 54            person = Species.objects.select_related(depth=10).get(name="sapiens")
 55            domain = person.genus.family.order.klass.phylum.kingdom.domain
 56            self.assertEqual(domain.name, 'Eukaryota')
 57        self.assertNumQueries(1, test)
 58
 59    def test_list_without_select_related(self):
 60        """
 61        select_related() also of course applies to entire lists, not just
 62        items. This test verifies the expected behavior without select_related.
 63        """
 64        def test():
 65            world = Species.objects.all()
 66            families = [o.genus.family.name for o in world]
 67            self.assertEqual(sorted(families), [
 68                'Amanitacae',
 69                'Drosophilidae',
 70                'Fabaceae',
 71                'Hominidae',
 72            ])
 73        self.assertNumQueries(9, test)
 74
 75    def test_list_with_select_related(self):
 76        """
 77        select_related() also of course applies to entire lists, not just
 78        items. This test verifies the expected behavior with select_related.
 79        """
 80        def test():
 81            world = Species.objects.all().select_related()
 82            families = [o.genus.family.name for o in world]
 83            self.assertEqual(sorted(families), [
 84                'Amanitacae',
 85                'Drosophilidae',
 86                'Fabaceae',
 87                'Hominidae',
 88            ])
 89        self.assertNumQueries(1, test)
 90
 91    def test_depth(self, depth=1, expected=7):
 92        """
 93        The "depth" argument to select_related() will stop the descent at a
 94        particular level.
 95        """
 96        def test():
 97            pea = Species.objects.select_related(depth=depth).get(name="sativum")
 98            self.assertEqual(
 99                pea.genus.family.order.klass.phylum.kingdom.domain.name,
100                'Eukaryota'
101            )
102        # Notice: one fewer queries than above because of depth=1
103        self.assertNumQueries(expected, test)
104
105    def test_larger_depth(self):
106        """
107        The "depth" argument to select_related() will stop the descent at a
108        particular level.  This tests a larger depth value.
109        """
110        self.test_depth(depth=5, expected=3)
111
112    def test_list_with_depth(self):
113        """
114        The "depth" argument to select_related() will stop the descent at a
115        particular level. This can be used on lists as well.
116        """
117        def test():
118            world = Species.objects.all().select_related(depth=2)
119            orders = [o.genus.family.order.name for o in world]
120            self.assertEqual(sorted(orders),
121                ['Agaricales', 'Diptera', 'Fabales', 'Primates'])
122        self.assertNumQueries(5, test)
123
124    def test_select_related_with_extra(self):
125        s = Species.objects.all().select_related(depth=1)\
126            .extra(select={'a': 'select_related_species.id + 10'})[0]
127        self.assertEqual(s.id + 10, s.a)
128
129    def test_certain_fields(self):
130        """
131        The optional fields passed to select_related() control which related
132        models we pull in. This allows for smaller queries and can act as an
133        alternative (or, in addition to) the depth parameter.
134
135        In this case, we explicitly say to select the 'genus' and
136        'genus.family' models, leading to the same number of queries as before.
137        """
138        def test():
139            world = Species.objects.select_related('genus__family')
140            families = [o.genus.family.name for o in world]
141            self.assertEqual(sorted(families),
142                ['Amanitacae', 'Drosophilidae', 'Fabaceae', 'Hominidae'])
143        self.assertNumQueries(1, test)
144
145    def test_more_certain_fields(self):
146        """
147        In this case, we explicitly say to select the 'genus' and
148        'genus.family' models, leading to the same number of queries as before.
149        """
150        def test():
151            world = Species.objects.filter(genus__name='Amanita')\
152                .select_related('genus__family')
153            orders = [o.genus.family.order.name for o in world]
154            self.assertEqual(orders, [u'Agaricales'])
155        self.assertNumQueries(2, test)
156
157    def test_field_traversal(self):
158        def test():
159            s = Species.objects.all().select_related('genus__family__order'
160                ).order_by('id')[0:1].get().genus.family.order.name
161            self.assertEqual(s, u'Diptera')
162        self.assertNumQueries(1, test)
163
164    def test_depth_fields_fails(self):
165        self.assertRaises(TypeError,
166            Species.objects.select_related,
167            'genus__family__order', depth=4
168        )