add atomic conditions to save
Conflicts: mongoengine/document.py
This commit is contained in:
		
				
					committed by
					
						 Frank Battaglia
						Frank Battaglia
					
				
			
			
				
	
			
			
			
						parent
						
							d4b3649640
						
					
				
				
					commit
					db1e69813b
				
			| @@ -13,7 +13,8 @@ from mongoengine.base import (DocumentMetaclass, TopLevelDocumentMetaclass, | |||||||
|                               BaseDocument, BaseDict, BaseList, |                               BaseDocument, BaseDict, BaseList, | ||||||
|                               ALLOW_INHERITANCE, get_document) |                               ALLOW_INHERITANCE, get_document) | ||||||
| from mongoengine.errors import ValidationError | from mongoengine.errors import ValidationError | ||||||
| from mongoengine.queryset import OperationError, NotUniqueError, QuerySet | from mongoengine.queryset import (OperationError, NotUniqueError, | ||||||
|  |                                   QuerySet, transform) | ||||||
| from mongoengine.connection import get_db, DEFAULT_CONNECTION_NAME | from mongoengine.connection import get_db, DEFAULT_CONNECTION_NAME | ||||||
| from mongoengine.context_managers import switch_db, switch_collection | from mongoengine.context_managers import switch_db, switch_collection | ||||||
|  |  | ||||||
| @@ -180,7 +181,7 @@ class Document(BaseDocument): | |||||||
|  |  | ||||||
|     def save(self, force_insert=False, validate=True, clean=True, |     def save(self, force_insert=False, validate=True, clean=True, | ||||||
|              write_concern=None,  cascade=None, cascade_kwargs=None, |              write_concern=None,  cascade=None, cascade_kwargs=None, | ||||||
|              _refs=None, **kwargs): |              _refs=None, save_condition=None, **kwargs): | ||||||
|         """Save the :class:`~mongoengine.Document` to the database. If the |         """Save the :class:`~mongoengine.Document` to the database. If the | ||||||
|         document already exists, it will be updated, otherwise it will be |         document already exists, it will be updated, otherwise it will be | ||||||
|         created. |         created. | ||||||
| @@ -203,7 +204,8 @@ class Document(BaseDocument): | |||||||
|         :param cascade_kwargs: (optional) kwargs dictionary to be passed throw |         :param cascade_kwargs: (optional) kwargs dictionary to be passed throw | ||||||
|             to cascading saves.  Implies ``cascade=True``. |             to cascading saves.  Implies ``cascade=True``. | ||||||
|         :param _refs: A list of processed references used in cascading saves |         :param _refs: A list of processed references used in cascading saves | ||||||
|  |         :param save_condition: only perform save if matching record in db | ||||||
|  |             satisfies condition(s) (e.g., version number) | ||||||
|         .. versionchanged:: 0.5 |         .. versionchanged:: 0.5 | ||||||
|             In existing documents it only saves changed fields using |             In existing documents it only saves changed fields using | ||||||
|             set / unset.  Saves are cascaded and any |             set / unset.  Saves are cascaded and any | ||||||
| @@ -217,6 +219,9 @@ class Document(BaseDocument): | |||||||
|             meta['cascade'] = True.  Also you can pass different kwargs to |             meta['cascade'] = True.  Also you can pass different kwargs to | ||||||
|             the cascade save using cascade_kwargs which overwrites the |             the cascade save using cascade_kwargs which overwrites the | ||||||
|             existing kwargs with custom values. |             existing kwargs with custom values. | ||||||
|  |         .. versionchanged:: 0.8.5 | ||||||
|  |             Optional save_condition that only overwrites existing documents | ||||||
|  |             if the condition is satisfied in the current db record. | ||||||
|         """ |         """ | ||||||
|         signals.pre_save.send(self.__class__, document=self) |         signals.pre_save.send(self.__class__, document=self) | ||||||
|  |  | ||||||
| @@ -230,7 +235,8 @@ class Document(BaseDocument): | |||||||
|  |  | ||||||
|         created = ('_id' not in doc or self._created or force_insert) |         created = ('_id' not in doc or self._created or force_insert) | ||||||
|  |  | ||||||
|         signals.pre_save_post_validation.send(self.__class__, document=self, created=created) |         signals.pre_save_post_validation.send(self.__class__, document=self, | ||||||
|  |                                               created=created) | ||||||
|  |  | ||||||
|         try: |         try: | ||||||
|             collection = self._get_collection() |             collection = self._get_collection() | ||||||
| @@ -243,7 +249,12 @@ class Document(BaseDocument): | |||||||
|                 object_id = doc['_id'] |                 object_id = doc['_id'] | ||||||
|                 updates, removals = self._delta() |                 updates, removals = self._delta() | ||||||
|                 # Need to add shard key to query, or you get an error |                 # Need to add shard key to query, or you get an error | ||||||
|                 select_dict = {'_id': object_id} |                 if save_condition is not None: | ||||||
|  |                     select_dict = transform.query(self.__class__, | ||||||
|  |                                                   **save_condition) | ||||||
|  |                 else: | ||||||
|  |                     select_dict = {} | ||||||
|  |                 select_dict['_id'] = object_id | ||||||
|                 shard_key = self.__class__._meta.get('shard_key', tuple()) |                 shard_key = self.__class__._meta.get('shard_key', tuple()) | ||||||
|                 for k in shard_key: |                 for k in shard_key: | ||||||
|                     actual_key = self._db_field_map.get(k, k) |                     actual_key = self._db_field_map.get(k, k) | ||||||
| @@ -263,10 +274,12 @@ class Document(BaseDocument): | |||||||
|                 if removals: |                 if removals: | ||||||
|                     update_query["$unset"] = removals |                     update_query["$unset"] = removals | ||||||
|                 if updates or removals: |                 if updates or removals: | ||||||
|  |                     upsert = save_condition is None | ||||||
|                     last_error = collection.update(select_dict, update_query, |                     last_error = collection.update(select_dict, update_query, | ||||||
|                                                    upsert=True, **write_concern) |                                                    upsert=upsert, **write_concern) | ||||||
|                     created = is_new_object(last_error) |                     created = is_new_object(last_error) | ||||||
|  |  | ||||||
|  |  | ||||||
|             if cascade is None: |             if cascade is None: | ||||||
|                 cascade = self._meta.get('cascade', False) or cascade_kwargs is not None |                 cascade = self._meta.get('cascade', False) or cascade_kwargs is not None | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user