Querysets now return clones and are no longer edit in place

Fixes #56
This commit is contained in:
Ross Lawley 2013-01-04 09:41:08 +00:00
parent 09a5f5c8f3
commit 9bbd8dbe62
6 changed files with 656 additions and 570 deletions

View File

@ -26,6 +26,7 @@ Changes in 0.8.X
- Fix Django timezone support (#151) - Fix Django timezone support (#151)
- Simplified Q objects, removed QueryTreeTransformerVisitor (#98) (#171) - Simplified Q objects, removed QueryTreeTransformerVisitor (#98) (#171)
- FileFields now copyable (#198) - FileFields now copyable (#198)
- Querysets now return clones and are no longer edit in place (#56)
Changes in 0.7.9 Changes in 0.7.9
================ ================

View File

@ -56,6 +56,28 @@ you will need to declare :attr:`allow_inheritance` in the meta data like so: ::
meta = {'allow_inheritance': True} meta = {'allow_inheritance': True}
Querysets
~~~~~~~~~
Querysets now return clones and should no longer be considered editable in
place. This brings us in line with how Django's querysets work and removes a
long running gotcha. If you edit your querysets inplace you will have to
update your code like so: ::
# Old code:
mammals = Animal.objects(type="mammal")
mammals.filter(order="Carnivora") # Returns a cloned queryset that isn't assigned to anything - so this will break in 0.8
[m for m in mammals] # This will return all mammals in 0.8 as the 2nd filter returned a new queryset
# Update example a) assign queryset after a change:
mammals = Animal.objects(type="mammal")
carnivores = mammals.filter(order="Carnivora") # Reassign the new queryset so fitler can be applied
[m for m in carnivores] # This will return all carnivores
# Update example b) chain the queryset:
mammals = Animal.objects(type="mammal").filter(order="Carnivora") # The final queryset is assgined to mammals
[m for m in mammals] # This will return all carnivores
Indexes Indexes
------- -------

View File

@ -28,8 +28,10 @@ def register_connection(alias, name, host='localhost', port=27017,
:param name: the name of the specific database to use :param name: the name of the specific database to use
:param host: the host name of the :program:`mongod` instance to connect to :param host: the host name of the :program:`mongod` instance to connect to
:param port: the port that the :program:`mongod` instance is running on :param port: the port that the :program:`mongod` instance is running on
:param is_slave: whether the connection can act as a slave ** Depreciated pymongo 2.0.1+ :param is_slave: whether the connection can act as a slave
:param read_preference: The read preference for the collection ** Added pymongo 2.1 ** Depreciated pymongo 2.0.1+
:param read_preference: The read preference for the collection
** Added pymongo 2.1
:param slaves: a list of aliases of slave connections; each of these must :param slaves: a list of aliases of slave connections; each of these must
be a registered connection that has :attr:`is_slave` set to ``True`` be a registered connection that has :attr:`is_slave` set to ``True``
:param username: username to authenticate with :param username: username to authenticate with

File diff suppressed because it is too large Load Diff

View File

@ -713,19 +713,19 @@ class QuerySetTest(unittest.TestCase):
self.assertEqual(p._cursor_args, self.assertEqual(p._cursor_args,
{'snapshot': False, 'slave_okay': False, 'timeout': True}) {'snapshot': False, 'slave_okay': False, 'timeout': True})
p.snapshot(False).slave_okay(False).timeout(False) p = p.snapshot(False).slave_okay(False).timeout(False)
self.assertEqual(p._cursor_args, self.assertEqual(p._cursor_args,
{'snapshot': False, 'slave_okay': False, 'timeout': False}) {'snapshot': False, 'slave_okay': False, 'timeout': False})
p.snapshot(True).slave_okay(False).timeout(False) p = p.snapshot(True).slave_okay(False).timeout(False)
self.assertEqual(p._cursor_args, self.assertEqual(p._cursor_args,
{'snapshot': True, 'slave_okay': False, 'timeout': False}) {'snapshot': True, 'slave_okay': False, 'timeout': False})
p.snapshot(True).slave_okay(True).timeout(False) p = p.snapshot(True).slave_okay(True).timeout(False)
self.assertEqual(p._cursor_args, self.assertEqual(p._cursor_args,
{'snapshot': True, 'slave_okay': True, 'timeout': False}) {'snapshot': True, 'slave_okay': True, 'timeout': False})
p.snapshot(True).slave_okay(True).timeout(True) p = p.snapshot(True).slave_okay(True).timeout(True)
self.assertEqual(p._cursor_args, self.assertEqual(p._cursor_args,
{'snapshot': True, 'slave_okay': True, 'timeout': True}) {'snapshot': True, 'slave_okay': True, 'timeout': True})
@ -773,7 +773,8 @@ class QuerySetTest(unittest.TestCase):
self.assertEqual(len(docs), 1000) self.assertEqual(len(docs), 1000)
# Limit and skip # Limit and skip
self.assertEqual('[<Doc: 1>, <Doc: 2>, <Doc: 3>]', "%s" % docs[1:4]) docs = docs[1:4]
self.assertEqual('[<Doc: 1>, <Doc: 2>, <Doc: 3>]', "%s" % docs)
self.assertEqual(docs.count(), 3) self.assertEqual(docs.count(), 3)
self.assertEqual(len(docs), 3) self.assertEqual(len(docs), 3)

View File

@ -202,8 +202,8 @@ class QTest(unittest.TestCase):
self.assertEqual(test2.count(), 3) self.assertEqual(test2.count(), 3)
self.assertFalse(test2 == test) self.assertFalse(test2 == test)
test2.filter(x=6) test3 = test2.filter(x=6)
self.assertEqual(test2.count(), 1) self.assertEqual(test3.count(), 1)
self.assertEqual(test.count(), 3) self.assertEqual(test.count(), 3)
def test_q(self): def test_q(self):