Added upsert_one method on BaseQuerySet and modified test_upsert_one

This commit is contained in:
srossiter 2015-11-24 12:46:38 +00:00
parent a6e996d921
commit b7b28390df
4 changed files with 40 additions and 3 deletions

View File

@ -231,3 +231,4 @@ that much better:
* Lars Butler (https://github.com/larsbutler) * Lars Butler (https://github.com/larsbutler)
* George Macon (https://github.com/gmacon) * George Macon (https://github.com/gmacon)
* Ashley Whetter (https://github.com/AWhetter) * Ashley Whetter (https://github.com/AWhetter)
* Steven Rossiter (https://github.com/BeardedSteve)

View File

@ -14,7 +14,7 @@ import errors
__all__ = (list(document.__all__) + fields.__all__ + connection.__all__ + __all__ = (list(document.__all__) + fields.__all__ + connection.__all__ +
list(queryset.__all__) + signals.__all__ + list(errors.__all__)) list(queryset.__all__) + signals.__all__ + list(errors.__all__))
VERSION = (0, 10, 1) VERSION = (0, 10, 2)
def get_version(): def get_version():

View File

@ -471,6 +471,33 @@ class BaseQuerySet(object):
raise OperationError(message) raise OperationError(message)
raise OperationError(u'Update failed (%s)' % unicode(err)) raise OperationError(u'Update failed (%s)' % unicode(err))
def upsert_one(self, write_concern=None, **update):
"""Perform an atomic upsert on the fields of the first document
matched by the query.
:param write_concern: Extra keyword arguments are passed down which
will be used as options for the resultant
``getLastError`` command. For example,
``save(..., write_concern={w: 2, fsync: True}, ...)`` will
wait until at least two servers have recorded the write and
will force an fsync on the primary server.
:param update: Django-style update keyword arguments
:returns the new or overwritten document
.. versionadded:: 10.0.2
"""
update = self.update(multi=False, upsert=True, write_concern=write_concern,
full_result=True,**update)
if update['updatedExisting']:
document = self.get()
else:
document = self._document.objects.with_id(update['upserted'])
return document
def update_one(self, upsert=False, write_concern=None, **update): def update_one(self, upsert=False, write_concern=None, **update):
"""Perform an atomic update on the fields of the first document """Perform an atomic update on the fields of the first document
matched by the query. matched by the query.

View File

@ -680,12 +680,21 @@ class QuerySetTest(unittest.TestCase):
def test_upsert_one(self): def test_upsert_one(self):
self.Person.drop_collection() self.Person.drop_collection()
self.Person.objects(name="Bob", age=30).update_one(upsert=True) bob = self.Person.objects(name="Bob", age=30).upsert_one()
bob = self.Person.objects.first()
self.assertEqual("Bob", bob.name) self.assertEqual("Bob", bob.name)
self.assertEqual(30, bob.age) self.assertEqual(30, bob.age)
bob.name = "Bobby"
bob.save()
bobby = self.Person.objects(name="Bobby", age=30).upsert_one()
self.assertEqual("Bobby", bobby.name)
self.assertEqual(30, bobby.age)
self.assertEqual(bob.id, bobby.id)
def test_set_on_insert(self): def test_set_on_insert(self):
self.Person.drop_collection() self.Person.drop_collection()