1
0
mirror of https://github.com/django/django.git synced 2025-07-07 11:19:12 +00:00

queryset-refactor: Fixed a possibility of shooting oneself in the foot and

creating infinite recursion with select_related(). Refs #3045, #3288.


git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6521 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-10-15 05:51:19 +00:00
parent 3429fc0ff2
commit 8c10e0d00e
3 changed files with 24 additions and 3 deletions

View File

@ -294,6 +294,7 @@ class _QuerySet(object):
"""Returns a new QuerySet instance that will select related objects.""" """Returns a new QuerySet instance that will select related objects."""
obj = self._clone() obj = self._clone()
obj.query.select_related = true_or_false obj.query.select_related = true_or_false
if depth:
obj.query.max_depth = depth obj.query.max_depth = depth
return obj return obj

View File

@ -87,7 +87,10 @@ class Query(object):
self.low_mark, self.high_mark = 0, None # Used for offset/limit self.low_mark, self.high_mark = 0, None # Used for offset/limit
self.distinct = False self.distinct = False
self.select_related = False self.select_related = False
self.max_depth = 0
# Arbitrary maximum limit for select_related to prevent infinite
# recursion. Can be changed by the depth parameter to select_related().
self.max_depth = 5
# These are for extensions. The contents are more or less appended # These are for extensions. The contents are more or less appended
# verbatim to the appropriate clause. # verbatim to the appropriate clause.

View File

@ -80,6 +80,14 @@ class Cover(models.Model):
def __unicode__(self): def __unicode__(self):
return self.title return self.title
# Some funky cross-linked models for testing a couple of infinite recursion
# cases.
class X(models.Model):
y = models.ForeignKey('Y')
class Y(models.Model):
x1 = models.ForeignKey(X, related_name='y1')
__test__ = {'API_TESTS':""" __test__ = {'API_TESTS':"""
>>> t1 = Tag(name='t1') >>> t1 = Tag(name='t1')
>>> t1.save() >>> t1.save()
@ -353,9 +361,18 @@ True
>>> ExtraInfo.objects.values('note') >>> ExtraInfo.objects.values('note')
[{'note': 1}, {'note': 2}] [{'note': 1}, {'note': 2}]
# Bug 5261 Bug #5261
>>> Note.objects.exclude(Q()) >>> Note.objects.exclude(Q())
[<Note: n1>, <Note: n2>, <Note: n3>] [<Note: n1>, <Note: n2>, <Note: n3>]
Bug #3045, #3288
Once upon a time, select_related() with circular relations would loop
infinitely if you forgot to specify "depth". Now we set an arbitrary default
upper bound.
>>> X.objects.all()
[]
>>> X.objects.select_related()
[]
"""} """}