Problem dereferencing non-binary UUID primary keys
Hi all, I have encountered a problem dereferencing instances when that have a primary key that is a UUID that is stored in mongodb as a string.
class Pool(db.Document):
uuid = db.UUIDField(required=True, primary_key=True, binary=False)
class Host(db.Document):
uuid = db.UUIDField(required=True, primary_key=True, binary=False )
pool = db.ReferenceField(Pool)
When I try to access to pool attribute I get a DBRef instance instead a Pool instance.
p = Pool(uuid="36a36f7b-54b7-724f-d28d-2262a629c18a")
h = Host(uuid="70a36f7b-1db7-724f-d28d-2262a629c36b")
h.pool = p
h.save()
host = Host.objects.get(uuid="70a36f7b-1db7-724f-d28d-2262a629c36b")
host.pool
DBRef('pool', UUID('36a36f7b-54b7-724f-d28d-2262a629c18a'))
The DBRef contains the UUID object but the value is stored as string in mongodb. So when this is used in the get of ReferenceField class the search is done using the UUID object instead of the string:
if self._auto_dereference and isinstance(value, DBRef):
value = self.document_type._get_db().dereference(value)
end return None
If the uuid is stored using binary=True all works fine.
Ok the problem seems to be in "to_python" of UUID field.
def to_python(self, value):
if not self._binary:
original_value = value
try:
if not isinstance(value, basestring):
value = unicode(value)
return uuid.UUID(value)
except:
return original_value
return value
The logic is reversed: if is not binary return a UUID object. Removing the "not" fix it for me.
nice catch @tudamp !
Would you like to submit a PR with the fix and a test case?
I've actually tested it and checked a bit the code, it is not that easy.
We have these UUIDField in order to always recreate them as UUID on the Python side and this should NOT be changed.
I don't know actually it we should change it or not, but the problem may rather be in the to_python() method of the ReferenceField class, where we do the following:
value = DBRef(collection, self.document_type.id.to_python(value))
which indeeds converts it to UUID always. It is the only point I would think to modify, but also I'm not sure.
@tudamp what is actually your problem with the current representation? What operation may you try to do afterwards that fails?
I have encountered this bug as well using 0.10.5. Is there a workaround for it?
As far as I checked, this still occurs today with mongoengine==0.28.2
Is there a known workaround for this ?
Can confirm this issue still exists in later versions. 0.27 in my case.