diff --git a/docs/changelog.rst b/docs/changelog.rst index aba3f6b2..e3d7c8df 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -23,6 +23,7 @@ Changes in 0.9.X - DEV - Document save raise an exception if save_condition fails #1005 - Fixes some internal _id handling issue. #961 - Updated URL and Email Field regex validators, added schemes argument to URLField validation. #652 +- Removed get_or_create() deprecated since 0.8.0. #300 Changes in 0.9.0 ================ diff --git a/docs/guide/querying.rst b/docs/guide/querying.rst index 9861ce56..1cde82cb 100644 --- a/docs/guide/querying.rst +++ b/docs/guide/querying.rst @@ -263,21 +263,11 @@ no document matches the query, and if more than one document matched the query. These exceptions are merged into your document definitions eg: `MyDoc.DoesNotExist` -A variation of this method exists, -:meth:`~mongoengine.queryset.QuerySet.get_or_create`, that will create a new -document with the query arguments if no documents match the query. An -additional keyword argument, :attr:`defaults` may be provided, which will be -used as default values for the new document, in the case that it should need -to be created:: - - >>> a, created = User.objects.get_or_create(name='User A', defaults={'age': 30}) - >>> b, created = User.objects.get_or_create(name='User A', defaults={'age': 40}) - >>> a.name == b.name and a.age == b.age - True - -.. warning:: - :meth:`~mongoengine.queryset.QuerySet.get_or_create` method is deprecated - since :mod:`mongoengine` 0.8. +A variation of this method, get_or_create() existed, but it was unsafe. It +could not be made safe, because there are no transactions in mongoDB. Other +approaches should be investigated, to ensure you don't accidentally duplicate +data when using something similar to this method. Therefore it was deprecated +in 0.8 and removed in 0.10. Default Document queries ======================== diff --git a/mongoengine/queryset/base.py b/mongoengine/queryset/base.py index 89eb9afa..c8a30783 100644 --- a/mongoengine/queryset/base.py +++ b/mongoengine/queryset/base.py @@ -258,54 +258,6 @@ class BaseQuerySet(object): """ return self._document(**kwargs).save() - def get_or_create(self, write_concern=None, auto_save=True, - *q_objs, **query): - """Retrieve unique object or create, if it doesn't exist. Returns a - tuple of ``(object, created)``, where ``object`` is the retrieved or - created object and ``created`` is a boolean specifying whether a new - object was created. Raises - :class:`~mongoengine.queryset.MultipleObjectsReturned` or - `DocumentName.MultipleObjectsReturned` if multiple results are found. - A new document will be created if the document doesn't exists; a - dictionary of default values for the new document may be provided as a - keyword argument called :attr:`defaults`. - - .. note:: This requires two separate operations and therefore a - race condition exists. Because there are no transactions in - mongoDB other approaches should be investigated, to ensure you - don't accidentally duplicate data when using this method. This is - now scheduled to be removed before 1.0 - - :param write_concern: optional extra keyword arguments used if we - have to create a new document. - Passes any write_concern onto :meth:`~mongoengine.Document.save` - - :param auto_save: if the object is to be saved automatically if - not found. - - .. deprecated:: 0.8 - .. versionchanged:: 0.6 - added `auto_save` - .. versionadded:: 0.3 - """ - msg = ("get_or_create is scheduled to be deprecated. The approach is " - "flawed without transactions. Upserts should be preferred.") - warnings.warn(msg, DeprecationWarning) - - defaults = query.get('defaults', {}) - if 'defaults' in query: - del query['defaults'] - - try: - doc = self.get(*q_objs, **query) - return doc, False - except self._document.DoesNotExist: - query.update(defaults) - doc = self._document(**query) - - if auto_save: - doc.save(write_concern=write_concern) - return doc, True - def first(self): """Retrieve the first object matching the query. """ diff --git a/tests/fields/fields.py b/tests/fields/fields.py index 1a5c2561..35e3ca39 100644 --- a/tests/fields/fields.py +++ b/tests/fields/fields.py @@ -2152,9 +2152,7 @@ class FieldTest(unittest.TestCase): obj = Product.objects(company=None).first() self.assertEqual(obj, me) - obj, created = Product.objects.get_or_create(company=None) - - self.assertEqual(created, False) + obj = Product.objects.get(company=None) self.assertEqual(obj, me) def test_reference_query_conversion(self): diff --git a/tests/queryset/queryset.py b/tests/queryset/queryset.py index 981d47f4..fbc8ce4a 100644 --- a/tests/queryset/queryset.py +++ b/tests/queryset/queryset.py @@ -340,8 +340,7 @@ class QuerySetTest(unittest.TestCase): write_concern = {"fsync": True} - author, created = self.Person.objects.get_or_create( - name='Test User', write_concern=write_concern) + author = self.Person.objects.create(name='Test User') author.save(write_concern=write_concern) result = self.Person.objects.update( @@ -730,38 +729,6 @@ class QuerySetTest(unittest.TestCase): self.assertEqual(record.embed_no_default.field, 2) self.assertEqual(record.embed.field, 2) - def test_get_or_create(self): - """Ensure that ``get_or_create`` returns one result or creates a new - document. - """ - person1 = self.Person(name="User A", age=20) - person1.save() - person2 = self.Person(name="User B", age=30) - person2.save() - - # Retrieve the first person from the database - self.assertRaises(MultipleObjectsReturned, - self.Person.objects.get_or_create) - self.assertRaises(self.Person.MultipleObjectsReturned, - self.Person.objects.get_or_create) - - # Use a query to filter the people found to just person2 - person, created = self.Person.objects.get_or_create(age=30) - self.assertEqual(person.name, "User B") - self.assertEqual(created, False) - - person, created = self.Person.objects.get_or_create(age__lt=30) - self.assertEqual(person.name, "User A") - self.assertEqual(created, False) - - # Try retrieving when no objects exists - new doc should be created - kwargs = dict(age=50, defaults={'name': 'User C'}) - person, created = self.Person.objects.get_or_create(**kwargs) - self.assertEqual(created, True) - - person = self.Person.objects.get(age=50) - self.assertEqual(person.name, "User C") - def test_bulk_insert(self): """Ensure that bulk insert works """