在使用 Google App Engine (GAE) 时,如果在 @classmethod 中创建记录,并且随后尝试在该 @classmethod 内修改该记录,那么这些更新可能无法被可靠地持久化到数据存储中。
以下是导致这种问题的一个示例代码:
@classmethod
def create(cls, obj):
"""Factory method for a new system entity using an System instance. Returns a System object (representation) including the meta_key."""
if isinstance(obj, System):
pass
else:
raise Exception('Object is not of type System.')
#check for duplicates
q = dbSystem.all(keys_only=True)
q.filter('meta_guid = ', obj.meta_guid)
if q.get(): #match exists already
raise Exception('dbSystem with this meta_guid already exists. Cannot create.')
# store stub so we can get the key
act = cls(
meta_status = obj.meta_status,
meta_type = obj.meta_type,
meta_guid = obj.meta_guid,
json = None,
lastupdated=datetime.datetime.now())
act.put()
# get the key for the datastore entity and add it to the representation
newkey = str(act.key())
# update our representation
obj.meta_key = newkey
# store the representation
act.json = jsonpickle.encode(obj)
act.put()
return(obj) #return the representation
在这个示例中,create() 方法首先检查是否有重复记录,然后创建一个新的记录并将其存储在数据存储中。最后,它更新表示形式并将其存储在数据存储中。
但是,在开发服务器上运行应用程序时,发现关联实体的 json 字段有时为 NULL。这表明对该实体的更新无法被可靠地持久化到数据存储中。
2. 解决方案
导致这个问题的原因是,在检查是否存在重复记录时,使用了 dbSystem.all(keys_only=True) 查询。这个查询不会返回对象的最新版本,而是可能返回一个旧版本。
为了解决这个问题,应该使用对象的键来获取对象。这样可以确保获得对象的最新版本。
修改后的代码如下:
@classmethod
def create(cls, obj):
"""Factory method for a new system entity using an System instance. Returns a System object (representation) including the meta_key."""
if isinstance(obj, System):
pass
else:
raise Exception('Object is not of type System.')
#check for duplicates
q = dbSystem.get(obj.key())
if q: #match exists already
raise Exception('dbSystem with this meta_guid already exists. Cannot create.')
# store stub so we can get the key
act = cls(
meta_status = obj.meta_status,
meta_type = obj.meta_type,
meta_guid = obj.meta_guid,
json = None,
lastupdated=datetime.datetime.now())
act.put()
# get the key for the datastore entity and add it to the representation
newkey = str(act.key())
# update our representation
obj.meta_key = newkey
# store the representation
act.json = jsonpickle.encode(obj)
act.put()
return(obj) #return the representation
在修改后的代码中,使用 dbSystem.get() 方法来获取对象。这个方法会返回对象的最新版本,从而确保对该实体的更新能够被可靠地持久化到数据存储中。