Fixed inner queryset looping (#204)

This commit is contained in:
Ross Lawley 2013-01-29 10:33:13 +00:00
parent 156ca44a13
commit 025e17701b
5 changed files with 67 additions and 4 deletions

View File

@ -143,3 +143,4 @@ that much better:
* Martin Alderete (https://github.com/malderete) * Martin Alderete (https://github.com/malderete)
* Nick Joyce * Nick Joyce
* Jared Forsyth * Jared Forsyth
* Kenneth Falck

View File

@ -47,6 +47,7 @@ Changes in 0.8.X
- Added the "get_decoded" method to the MongoSession class (#216) - Added the "get_decoded" method to the MongoSession class (#216)
- Fixed invalid choices error bubbling (#214) - Fixed invalid choices error bubbling (#214)
- Updated Save so it calls $set and $unset in a single operation (#211) - Updated Save so it calls $set and $unset in a single operation (#211)
- Fixed inner queryset looping (#204)
Changes in 0.7.9 Changes in 0.7.9
================ ================

View File

@ -112,8 +112,11 @@ class QuerySet(object):
def __iter__(self): def __iter__(self):
"""Support iterator protocol""" """Support iterator protocol"""
self.rewind() queryset = self
return self if queryset._iter:
queryset = self.clone()
queryset.rewind()
return queryset
def __len__(self): def __len__(self):
return self.count() return self.count()
@ -159,7 +162,6 @@ class QuerySet(object):
.. versionchanged:: 0.6.13 Now doesnt modify the cursor .. versionchanged:: 0.6.13 Now doesnt modify the cursor
""" """
if self._iter: if self._iter:
return '.. queryset mid-iteration ..' return '.. queryset mid-iteration ..'
@ -537,7 +539,7 @@ class QuerySet(object):
c._cursor_obj = self._cursor_obj.clone() c._cursor_obj = self._cursor_obj.clone()
if self._slice: if self._slice:
c._cursor_obj[self._slice] c._cursor[self._slice]
return c return c

View File

@ -3125,5 +3125,46 @@ class QuerySetTest(unittest.TestCase):
Organization)) Organization))
self.assertTrue(isinstance(qs.first().organization, Organization)) self.assertTrue(isinstance(qs.first().organization, Organization))
def test_nested_queryset_iterator(self):
# Try iterating the same queryset twice, nested.
names = ['Alice', 'Bob', 'Chuck', 'David', 'Eric', 'Francis', 'George']
class User(Document):
name = StringField()
def __unicode__(self):
return self.name
User.drop_collection()
for name in names:
User(name=name).save()
users = User.objects.all().order_by('name')
outer_count = 0
inner_count = 0
inner_total_count = 0
self.assertEqual(len(users), 7)
for i, outer_user in enumerate(users):
self.assertEqual(outer_user.name, names[i])
outer_count += 1
inner_count = 0
# Calling len might disrupt the inner loop if there are bugs
self.assertEqual(len(users), 7)
for j, inner_user in enumerate(users):
self.assertEqual(inner_user.name, names[j])
inner_count += 1
inner_total_count += 1
self.assertEqual(inner_count, 7) # inner loop should always be executed seven times
self.assertEqual(outer_count, 7) # outer loop should be executed seven times total
self.assertEqual(inner_total_count, 7 * 7) # inner loop should be executed fourtynine times total
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -136,7 +136,25 @@ class QuerySetTest(unittest.TestCase):
start = end - 1 start = end - 1
self.assertEqual(t.render(Context(d)), u'%d:%d:' % (start, end)) self.assertEqual(t.render(Context(d)), u'%d:%d:' % (start, end))
def test_nested_queryset_template_iterator(self):
# Try iterating the same queryset twice, nested, in a Django template.
names = ['A', 'B', 'C', 'D']
class User(Document):
name = StringField()
def __unicode__(self):
return self.name
User.drop_collection()
for name in names:
User(name=name).save()
users = User.objects.all().order_by('name')
template = Template("{% for user in users %}{{ user.name }}{% ifequal forloop.counter 2 %} {% for inner_user in users %}{{ inner_user.name }}{% endfor %} {% endifequal %}{% endfor %}")
rendered = template.render(Context({'users': users}))
self.assertEqual(rendered, 'AB ABCD CD')
class MongoDBSessionTest(SessionTestsMixin, unittest.TestCase): class MongoDBSessionTest(SessionTestsMixin, unittest.TestCase):
backend = SessionStore backend = SessionStore