Save no longer tramples over documents now sets or unsets explicit fields.
Fixes #146, refs #18 Thanks @zhangcheng for the initial code
This commit is contained in:
@@ -92,6 +92,9 @@ class BaseField(object):
|
||||
"""Descriptor for assigning a value to a field in a document.
|
||||
"""
|
||||
instance._data[self.name] = value
|
||||
# If the field set is in the _present_fields list add it so we can track
|
||||
if hasattr(instance, '_present_fields') and self.name not in instance._present_fields:
|
||||
instance._present_fields.append(self.name)
|
||||
|
||||
def to_python(self, value):
|
||||
"""Convert a MongoDB-compatible type to a Python type.
|
||||
@@ -592,13 +595,14 @@ class BaseDocument(object):
|
||||
if field.choices: # dynamically adds a way to get the display value for a field with choices
|
||||
setattr(self, 'get_%s_display' % attr_name, partial(self._get_FIELD_display, field=field))
|
||||
|
||||
# Use default value if present
|
||||
value = getattr(self, attr_name, None)
|
||||
setattr(self, attr_name, value)
|
||||
|
||||
# Assign initial values to instance
|
||||
for attr_name in values.keys():
|
||||
try:
|
||||
setattr(self, attr_name, values.pop(attr_name))
|
||||
value = values.pop(attr_name)
|
||||
setattr(self, attr_name, value)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
@@ -739,7 +743,6 @@ class BaseDocument(object):
|
||||
cls = subclasses[class_name]
|
||||
|
||||
present_fields = data.keys()
|
||||
|
||||
for field_name, field in cls._fields.items():
|
||||
if field.db_field in data:
|
||||
value = data[field.db_field]
|
||||
|
||||
@@ -95,6 +95,16 @@ class Document(BaseDocument):
|
||||
collection = self.__class__.objects._collection
|
||||
if force_insert:
|
||||
object_id = collection.insert(doc, safe=safe, **write_options)
|
||||
elif '_id' in doc:
|
||||
# Perform a set rather than a save - this will only save set fields
|
||||
object_id = doc.pop('_id')
|
||||
collection.update({'_id': object_id}, {"$set": doc}, upsert=True, safe=safe, **write_options)
|
||||
|
||||
# Find and unset any fields explicitly set to None
|
||||
if hasattr(self, '_present_fields'):
|
||||
removals = dict([(k, 1) for k in self._present_fields if k not in doc and k != '_id'])
|
||||
if removals:
|
||||
collection.update({'_id': object_id}, {"$unset": removals}, upsert=True, safe=safe, **write_options)
|
||||
else:
|
||||
object_id = collection.save(doc, safe=safe, **write_options)
|
||||
except pymongo.errors.OperationFailure, err:
|
||||
|
||||
Reference in New Issue
Block a user