Commits

Andy Mikhailenko committed 4afaf70

Bugfix: modeling.Document would not save _id properly.

Comments (0)

Files changed (2)

         data = db[cls.collection].find_one(*args, **kwargs)
         if data:
             return cls.wrap_incoming(data, db)
+        else:
+            return None
 
     def save(self, db):
         assert self.collection
+
         # XXX self.structure belongs to StructuredDictMixin !!
         outgoing = dict(dict_to_db(self, self.structure))
+
         object_id = db[self.collection].save(outgoing)
-        if '_id' in self:
-            assert self['_id'] == object_id
+
+        if self.get('_id') is None:
+            self['_id'] = object_id
         else:
-            self['_id'] = object_id
+            pass
+
+        return object_id
 
 
 class StructuredDictMixin(object):
 
     def save(self, db):
         self.validate()
-        super(Document, self).save(db)
+        return super(Document, self).save(db)
 
 
 def _db_to_dict_pairs(spec, data, db):
 
 def _dict_to_db_pairs(spec, data):
     for key, value in data.iteritems():
+        if key == '_id' and value is None:
+            # let the database assign an identifier
+            continue
         if isinstance(value, dict):
             if '_id' in value:
                 collection = spec[key].collection

unittests/test_modeling.py

 ==============
 """
 import pymongo
+from pymongo.objectid import ObjectId
 import pytest
 
 from monk import modeling
     class Entry(modeling.Document):
         collection = 'entries'
         structure = {
+            '_id': ObjectId,
             'title': unicode,
         }
 
         entry.save(self.db)
         assert self.collection.find().count() == 1
         assert self.collection.find({'title': u'Hello'}).count() == 1
+
+    def test_id(self):
+        entry = self.Entry(title=u'Hello')
+        assert entry['_id'] is None
+
+        # save the first time
+        obj_id = entry.save(self.db)
+        assert obj_id == entry['_id']
+        assert self.Entry.find(self.db).count() == 1
+        assert [entry] == list(self.Entry.find(self.db, _id=obj_id))
+
+        # update
+        entry.title = u'Bye'
+        same_id = entry.save(self.db)
+        assert obj_id == same_id
+        assert obj_id == entry['_id']
+        assert self.Entry.find(self.db).count() == 1