On Wed, Nov 7, 2012 at 3:07 PM, Roy Smith <r
...@panix.com> wrote:
> We have some bad data in our database (pre-existing our use of
> mongoengine). Some documents have an integer for a field which should be a
> string. I have a post_init() method which corrects these on the fly.
> Between 0.6.12 and 0.6.13, this broke. The attached script demonstrates
> the problem. It runs correctly under 0.6.12. On 0.6.13, it fails with:
> python bug.py
> doc = {'_id': ObjectId('509a77ace14c4e6a7fbb94ff'), 'year': 2000}
> Traceback (most recent call last):
> File "bug.py", line 34, in <module>
> song = Song.objects.get(id=doc['_id'])
> File
> "/home/roy/production/python/local/lib/python2.7/site-packages/mongoengine/ queryset.py",
> line 783, in get
> result1 = self.next()
> File
> "/home/roy/production/python/local/lib/python2.7/site-packages/mongoengine/ queryset.py",
> line 964, in next
> return self._document._from_son(self._cursor.next())
> File
> "/home/roy/production/python/local/lib/python2.7/site-packages/mongoengine/ base.py",
> line 974, in _from_son
> Invalid data to create a `%s` instance.\n%s""".strip() %
> (cls._class_name, errors))
> mongoengine.base.InvalidDocumentError: Invalid data to create a `Song`
> instance.
> year - 'int' object has no attribute 'decode'
> The problem is that my post_init() script doesn't get called in 0.6.13 (or
> perhaps the exception is thrown before post_init() gets a chance to run).
> I'm running:
> Python-2.7.3
> Ubuntu 12.04.1 LTS
> pymongo 2.3
> MongoDB 2.2.0
> ---------------------------------------------------------------------
> from pymongo import Connection
> from mongoengine import *
> from mongoengine import signals
> connect('test')
> class Song(Document):
> meta = {'collection': 'test_songs',
> 'allow_inheritance' : False,
> }
> year = StringField(required=True)
> def __unicode__(self):
> return "id=%r, year=%r" % (self.id, self.year)
> @classmethod
> def post_init(cls, sender, document, **kwargs):
> print "post_init()"
> if isinstance(document.year, int):
> print "fixing %r" % document
> document.year = str(document.year)
> # Hook-up post_init hook
> signals.post_init.connect(Song.post_init, sender=Song)
> # Create invalid document through raw pymongo connection
> doc = {"year": 2000}
> mongo = Connection()
> mongo.test.test_songs.insert(doc)
> print "doc = %s" % doc
> # Retrieve that document via mongoengine
> song = Song.objects.get(id=doc['_id'])
> print "song = %s" % song
> ---------------------------------------------------------------------
> --
> Roy Smith
> r...@panix.com