thirdparty/google_appengine/lib/django/tests/modeltests/select_related/models.py
changeset 2866 a04b1e4126c4
parent 2864 2e0b0af889be
child 2868 9f7f269383f7
equal deleted inserted replaced
2864:2e0b0af889be 2866:a04b1e4126c4
     1 """
       
     2 40. Tests for select_related()
       
     3 
       
     4 ``select_related()`` follows all relationships and pre-caches any foreign key
       
     5 values so that complex trees can be fetched in a single query. However, this
       
     6 isn't always a good idea, so the ``depth`` argument control how many "levels"
       
     7 the select-related behavior will traverse.
       
     8 """
       
     9 
       
    10 from django.db import models
       
    11 
       
    12 # Who remembers high school biology?
       
    13 
       
    14 class Domain(models.Model):
       
    15     name = models.CharField(maxlength=50)
       
    16     def __str__(self):
       
    17         return self.name
       
    18 
       
    19 class Kingdom(models.Model):
       
    20     name = models.CharField(maxlength=50)
       
    21     domain = models.ForeignKey(Domain)
       
    22     def __str__(self):
       
    23         return self.name
       
    24 
       
    25 class Phylum(models.Model):
       
    26     name = models.CharField(maxlength=50)
       
    27     kingdom = models.ForeignKey(Kingdom)
       
    28     def __str__(self):
       
    29         return self.name
       
    30     
       
    31 class Klass(models.Model):
       
    32     name = models.CharField(maxlength=50)
       
    33     phylum = models.ForeignKey(Phylum)
       
    34     def __str__(self):
       
    35         return self.name
       
    36     
       
    37 class Order(models.Model):
       
    38     name = models.CharField(maxlength=50)
       
    39     klass = models.ForeignKey(Klass)
       
    40     def __str__(self):
       
    41         return self.name
       
    42 
       
    43 class Family(models.Model):
       
    44     name = models.CharField(maxlength=50)
       
    45     order = models.ForeignKey(Order)
       
    46     def __str__(self):
       
    47         return self.name
       
    48 
       
    49 class Genus(models.Model):
       
    50     name = models.CharField(maxlength=50)
       
    51     family = models.ForeignKey(Family)
       
    52     def __str__(self):
       
    53         return self.name
       
    54 
       
    55 class Species(models.Model):
       
    56     name = models.CharField(maxlength=50)
       
    57     genus = models.ForeignKey(Genus)
       
    58     def __str__(self):
       
    59         return self.name
       
    60 
       
    61 def create_tree(stringtree):
       
    62     """Helper to create a complete tree"""
       
    63     names = stringtree.split()
       
    64     models = [Domain, Kingdom, Phylum, Klass, Order, Family, Genus, Species]
       
    65     assert len(names) == len(models), (names, models)
       
    66     
       
    67     parent = None
       
    68     for name, model in zip(names, models):
       
    69         try:
       
    70             obj = model.objects.get(name=name)
       
    71         except model.DoesNotExist:
       
    72             obj = model(name=name)
       
    73         if parent:
       
    74             setattr(obj, parent.__class__.__name__.lower(), parent)
       
    75         obj.save()
       
    76         parent = obj
       
    77 
       
    78 __test__ = {'API_TESTS':"""
       
    79 
       
    80 # Set up.
       
    81 # The test runner sets settings.DEBUG to False, but we want to gather queries
       
    82 # so we'll set it to True here and reset it at the end of the test suite.
       
    83 >>> from django.conf import settings
       
    84 >>> settings.DEBUG = True
       
    85 
       
    86 >>> create_tree("Eukaryota Animalia Anthropoda Insecta Diptera Drosophilidae Drosophila melanogaster")
       
    87 >>> create_tree("Eukaryota Animalia Chordata Mammalia Primates Hominidae Homo sapiens")
       
    88 >>> create_tree("Eukaryota Plantae Magnoliophyta Magnoliopsida Fabales Fabaceae Pisum sativum")
       
    89 >>> create_tree("Eukaryota Fungi Basidiomycota Homobasidiomycatae Agaricales Amanitacae Amanita muscaria")
       
    90 
       
    91 >>> from django import db
       
    92 
       
    93 # Normally, accessing FKs doesn't fill in related objects:
       
    94 >>> db.reset_queries()
       
    95 >>> fly = Species.objects.get(name="melanogaster")
       
    96 >>> fly.genus.family.order.klass.phylum.kingdom.domain
       
    97 <Domain: Eukaryota>
       
    98 >>> len(db.connection.queries)
       
    99 8
       
   100 
       
   101 # However, a select_related() call will fill in those related objects without any extra queries:
       
   102 >>> db.reset_queries()
       
   103 >>> person = Species.objects.select_related().get(name="sapiens")
       
   104 >>> person.genus.family.order.klass.phylum.kingdom.domain
       
   105 <Domain: Eukaryota>
       
   106 >>> len(db.connection.queries)
       
   107 1
       
   108 
       
   109 # select_related() also of course applies to entire lists, not just items.
       
   110 # Without select_related()
       
   111 >>> db.reset_queries()
       
   112 >>> world = Species.objects.all()
       
   113 >>> [o.genus.family for o in world]
       
   114 [<Family: Drosophilidae>, <Family: Hominidae>, <Family: Fabaceae>, <Family: Amanitacae>]
       
   115 >>> len(db.connection.queries)
       
   116 9
       
   117 
       
   118 # With select_related():
       
   119 >>> db.reset_queries()
       
   120 >>> world = Species.objects.all().select_related()
       
   121 >>> [o.genus.family for o in world]
       
   122 [<Family: Drosophilidae>, <Family: Hominidae>, <Family: Fabaceae>, <Family: Amanitacae>]
       
   123 >>> len(db.connection.queries)
       
   124 1
       
   125 
       
   126 # The "depth" argument to select_related() will stop the descent at a particular level:
       
   127 >>> db.reset_queries()
       
   128 >>> pea = Species.objects.select_related(depth=1).get(name="sativum")
       
   129 >>> pea.genus.family.order.klass.phylum.kingdom.domain
       
   130 <Domain: Eukaryota>
       
   131 
       
   132 # Notice: one few query than above because of depth=1
       
   133 >>> len(db.connection.queries)
       
   134 7
       
   135 
       
   136 >>> db.reset_queries()
       
   137 >>> pea = Species.objects.select_related(depth=5).get(name="sativum")
       
   138 >>> pea.genus.family.order.klass.phylum.kingdom.domain
       
   139 <Domain: Eukaryota>
       
   140 >>> len(db.connection.queries)
       
   141 3
       
   142 
       
   143 >>> db.reset_queries()
       
   144 >>> world = Species.objects.all().select_related(depth=2)
       
   145 >>> [o.genus.family.order for o in world]
       
   146 [<Order: Diptera>, <Order: Primates>, <Order: Fabales>, <Order: Agaricales>]
       
   147 >>> len(db.connection.queries)
       
   148 5
       
   149 
       
   150 # Reset DEBUG to where we found it.
       
   151 >>> settings.DEBUG = False
       
   152 """}