mongoengine中的迁移:InvalidId

dav*_*ave 7 python mongoengine

我正在使用mongoengine并尝试进行简单的迁移.我有一个字段,我想从StringField迁移到ReferenceField到另一个Object.我计划手动进行迁移,首先根据来自旧StringField的字符串构建新对象,然后显式设置它.

问题是,一旦我更改了字段类型,我甚至无法访问其中一个顶级文档.是否需要在我的文档的类代码中创建一个"虚拟"字段作为新字段的占位符?这对我来说似乎很糟糕所以我认为有更好的方法吗?

这是错误,这是因为来自DB(StringField)的字段与引用字段不一致.

/usr/lib/python2.7/site-packages/mongoengine/queryset/base.pyc in __getitem__(self, key)
    149                 return queryset._get_as_pymongo(queryset._cursor.next())
    150             return queryset._document._from_son(queryset._cursor[key],
--> 151                                                 _auto_dereference=self._auto_dereference)
    152         raise AttributeError
    153 

/usr/lib/python2.7/site-packages/mongoengine/base/document.pyc in _from_son(cls, son, _auto_dereference)
    568                 try:
    569                     data[field_name] = (value if value is None
--> 570                                         else field.to_python(value))
    571                     if field_name != field.db_field:
    572                         del data[field.db_field]

/usr/lib/python2.7/site-packages/mongoengine/fields.pyc in to_python(self, value)
    935            not isinstance(value, (DBRef, Document, EmbeddedDocument))):
    936             collection = self.document_type._get_collection_name()
--> 937             value = DBRef(collection, self.document_type.id.to_python(value))
    938         return value
    939 

/usr/lib/python2.7/site-packages/mongoengine/base/fields.pyc in to_python(self, value)
    390     def to_python(self, value):
    391         if not isinstance(value, ObjectId):
--> 392             value = ObjectId(value)
    393         return value
    394 

/usr/lib/python2.7/site-packages/bson/objectid.pyc in __init__(self, oid)
     88             self.__generate()
     89         else:
---> 90             self.__validate(oid)
     91 
     92     @classmethod

/usr/lib/python2.7/site-packages/bson/objectid.pyc in __validate(self, oid)
    192                     raise InvalidId("%s is not a valid ObjectId" % oid)
    193             else:
--> 194                 raise InvalidId("%s is not a valid ObjectId" % oid)
    195         else:
    196             raise TypeError("id must be an instance of (%s, %s, ObjectId), "

InvalidId: Was Dirty: a2111fe89383bb562738b81c2b63fe78e877ed32 is not a valid ObjectId
Run Code Online (Sandbox Code Playgroud)

mvr*_*mvr 0

我总是使用中间集合或同一集合中的中间字段手动迁移内容,但这个示例使您看起来不必这样做。堆栈溢出讨厌外部链接,因此我逐字包含下面的示例。顺便说一句,请小心“drop_collection”部分!

import unittest
from mongoengine import *


class Test(unittest.TestCase):

    def setUp(self):
        conn = connect(db='mongoenginetest')

    def create_old_data(self):
        class Person(Document):
            name = StringField()
            age = FloatField()  # Save as string

            meta = {'allow_inheritance': True}

        Person.drop_collection()

        Person(name="Rozza", age=35.00).save()

        rozza = Person._get_collection().find_one()
        self.assertEqual(35.00, rozza['age'])

    def test_migration(self):

        self.create_old_data()

        class Person(Document):
            name = StringField()
            age = StringField()

            meta = {'allow_inheritance': True}

        for p in Person.objects:
            p.age = "%s" % p.age
            p.save()

        rozza = Person.objects.first()
        self.assertEqual("35.0", rozza.age)

if __name__ == '__main__':
    unittest.main()
Run Code Online (Sandbox Code Playgroud)