Reputation: 1441
I've been struggling with an odd bug while working with MongoAlchemy.
I have a name = db.StringField()
on my Participant
model. Most of the time it works fine, but for some reason, the field is occasionally overwritten by a QueryField
. If I re-load my Participant
class from the module, it works fine for a while, but then breaks again.
Here is a terminal session where this occurred:
In [99]: from webapp.models import *
In [100]: Participant.by_name('yaronTesting') # My own method, which filters by name
Out[100]: <Participant yaronTesting>
In [101]: Participant.query.all()
Out[101]: [<Participant name>, <Participant name>]
# What?
In [102]: Participant.query.all()[0]
Out[102]: <Participant name>
In [103]: Participant.query.all()[0].name
Out[103]: QueryField(name)
In [104]: from webapp.models import Participant
In [105]: Participant.query.all()
Out[105]: [<Participant yaronTesting>, <Participant tsviki>]
In [106]: Participant.query.all()[0].name
Out[106]: u'yaronTesting'
I'm new to MongoDB and quite nervous about putting this into production -- does anyone know what might be going on behind the scenes?
So in response to Jeff's comment, I've got another session where the issue happens outside of querying:
In [168]: tsviki_old
Out[168]: <Participant name>
In [169]: tsviki_old.mongo_id
Out[169]: ObjectId('53f4f27a6c4dae23aba41419')
In [170]: tsviki_new = Participant.by_name('tsviki')
Out[170]: <Participant tsviki>
In [171]: tsviki_new.mongo_id
Out[171]: ObjectId('53f4f27a6c4dae23aba41419')
In [172]: tsviki_old.mongo_id
Out[172]: ObjectId('53f4f27a6c4dae23aba41419')
In [173]: tsviki_old
Out[173]: <Participant name>
In [174]: tsviki_new
Out[174]: <Participant tsviki>
In [175]: tsviki_old.name
Out[175]: QueryField(name)
In [176]: tsviki_new.name
Out[176]: u'tsviki'
In [179]: tsviki_old.created
Out[179]: QueryField(created)
In [180]: tsviki_old.modified
Out[180]: QueryField(modified)
In [181]: tsviki_old.sessions
Out[181]: QueryField(sessions)
# It happened again! To tsviki_new!
In [182]: tsviki_new.created
Out[182]: QueryField(created)
In [183]: tsviki_new
Out[183]: <Participant name>
In [184]: tsviki_new.name
Out[184]: QueryField(name)
In [185]: tsviki_new.mongo_id
Out[185]: ObjectId('53f4f27a6c4dae23aba41419')
I don't recall doing anything else while I was working on this last session, except maybe saving a file at one point. There seems to be some time-related component -- it usually occurs if I leave the interpreter for a while and come back, but there's no particular behavior I can pinpoint as having caused this.
Also, FYI:
@classmethod
def by_name(cls, name):
return Participant.query.filter({'name': name}).first()
And finally, here is the error when I add the name
field to the __init__
function and try to instantiate some objects (the earlier version passed no arguments to init):
In [36]: Participant.query.all()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-36-310f11265a76> in <module>()
----> 1 Participant.query.all()
/Users/kronosapiens/Dropbox/Documents/Development/code/environments/pm/lib/python2.7/site-packages/mongoalchemy/query.pyc in all(self)
177 def all(self):
178 ''' Return all of the results of a query in a list'''
--> 179 return [obj for obj in iter(self)]
180
181 def distinct(self, key):
/Users/kronosapiens/Dropbox/Documents/Development/code/environments/pm/lib/python2.7/site-packages/mongoalchemy/query.pyc in next(self)
410
411 def next(self):
--> 412 return self._next_internal()
413 __next__ = next
414
/Users/kronosapiens/Dropbox/Documents/Development/code/environments/pm/lib/python2.7/site-packages/mongoalchemy/query.pyc in _next_internal(self)
421 if obj:
422 return obj
--> 423 value = self.session._unwrap(self.type, value, fields=self.fields)
424 if not isinstance(value, dict):
425 self.session.cache_write(value)
/Users/kronosapiens/Dropbox/Documents/Development/code/environments/pm/lib/python2.7/site-packages/mongoalchemy/session.pyc in _unwrap(self, type, obj, **kwargs)
333 def _unwrap(self, type, obj, **kwargs):
334 obj = type.transform_incoming(obj, session=self)
--> 335 return type.unwrap(obj, session=self, **kwargs)
336
337 @property
/Users/kronosapiens/Dropbox/Documents/Development/code/environments/pm/lib/python2.7/site-packages/mongoalchemy/document.pyc in unwrap(cls, obj, fields, session)
494 if fields is not None:
495 params['retrieved_fields'] = fields
--> 496 obj = cls(loading_from_db=True, **params)
497 obj._mark_clean()
498 obj._session = session
/Users/kronosapiens/Dropbox/Documents/Development/code/jobs/paragon/webapp/webapp/models.py in __init__(self, name, **kwargs)
319
320 def __init__(self, name, **kwargs):
--> 321 super(Participant, self).__init__(
322 name=name,
323 **kwargs)
TypeError: super(type, obj): obj must be an instance or subtype of type
Upvotes: 2
Views: 207
Reputation: 158
MongoAlchemy author here. I'm not super familiar with the flask integration since someone else wrote it, but what must be happening here is that all() is returning an instance of the class Participant rather than an instance created from the database data.
If you can give a complete runnable example I could give you more details, but that's all I can glean from your question as stated.
Upvotes: 0