Code

Ticket #3288: 3288_96.diff

File 3288_96.diff, 3.5 KB (added by PhiR, 7 years ago)

fix and tests, backported to 0.96

Line 
1diff -uri /home/Philippe/Django-0.96/django/db/models/query.py ./django/db/models/query.py
2--- /home/Philippe/Django-0.96/django/db/models/query.py        2007-03-22 04:00:12.000000000 +0100
3+++ ./django/db/models/query.py 2007-09-16 15:57:51.859375000 +0200
4@@ -488,7 +488,7 @@
5 
6         # Add additional tables and WHERE clauses based on select_related.
7         if self._select_related:
8-            fill_table_cache(opts, select, tables, where,
9+            fill_table_cache(self.model, select, tables, where,
10                              old_prefix=opts.db_table,
11                              cache_tables_seen=[opts.db_table],
12                              max_depth=self._max_related_depth)
13@@ -753,7 +753,7 @@
14                 setattr(obj, f.get_cache_name(), rel_obj)
15     return obj, index_end
16 
17-def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen, max_depth=0, cur_depth=0):
18+def fill_table_cache(cls, select, tables, where, old_prefix, cache_tables_seen, max_depth=0, cur_depth=0):
19     """
20     Helper function that recursively populates the select, tables and where (in
21     place) for select_related queries.
22@@ -763,9 +763,11 @@
23     if max_depth and cur_depth > max_depth:
24         return None
25     
26+    opts = cls._meta
27     qn = backend.quote_name
28     for f in opts.fields:
29-        if f.rel and not f.null:
30+        # we only visit FKs, and exclude those that can be null and those who point to our own Model
31+        if f.rel and not f.null and f.rel.to != cls:
32             db_table = f.rel.to._meta.db_table
33             if db_table not in cache_tables_seen:
34                 tables.append(qn(db_table))
35@@ -777,7 +779,7 @@
36             where.append('%s.%s = %s.%s' % \
37                 (qn(old_prefix), qn(f.column), qn(db_table), qn(f.rel.get_related_field().column)))
38             select.extend(['%s.%s' % (qn(db_table), qn(f2.column)) for f2 in f.rel.to._meta.fields])
39-            fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen, max_depth, cur_depth+1)
40+            fill_table_cache(f.rel.to, select, tables, where, db_table, cache_tables_seen, max_depth, cur_depth+1)
41 
42 def parse_lookup(kwarg_items, opts):
43     # Helper function that handles converting API kwargs
44diff -uri /home/Philippe/Django-0.96/tests/modeltests/select_related/models.py ./tests/modeltests/select_related/models.py
45--- /home/Philippe/Django-0.96/tests/modeltests/select_related/models.py        2007-03-23 21:18:58.000000000 +0100
46+++ ./tests/modeltests/select_related/models.py 2007-09-16 16:01:30.609375000 +0200
47@@ -75,6 +75,16 @@
48         obj.save()
49         parent = obj
50 
51+# tests that select_related doesn't follow this kind of FK
52+class Foo(models.Model):
53+    parent = models.ForeignKey('self')
54+
55+class ALoop(models.Model):
56+    b = models.ForeignKey('BLoop')
57+
58+class BLoop(models.Model):
59+    a = models.ForeignKey('BLoop')
60+   
61 __test__ = {'API_TESTS':"""
62 
63 # Set up.
64@@ -83,6 +93,16 @@
65 >>> from django.conf import settings
66 >>> settings.DEBUG = True
67 
68+# simply verify that it's possible en enable select related on this model
69+>>> Foo.objects.all().select_related()
70+[]
71+
72+# simply verify that it's possible en enable select related on this model
73+>>> ALoop.objects.all().select_related()
74+[]
75+>>> BLoop.objects.all().select_related()
76+[]
77+
78 >>> create_tree("Eukaryota Animalia Anthropoda Insecta Diptera Drosophilidae Drosophila melanogaster")
79 >>> create_tree("Eukaryota Animalia Chordata Mammalia Primates Hominidae Homo sapiens")
80 >>> create_tree("Eukaryota Plantae Magnoliophyta Magnoliopsida Fabales Fabaceae Pisum sativum")