如何确保在 GAE 中使用 @classmethod 创建的记录能够被可靠地修改

51 阅读2分钟

在使用 Google App Engine (GAE) 时,如果在 @classmethod 中创建记录,并且随后尝试在该 @classmethod 内修改该记录,那么这些更新可能无法被可靠地持久化到数据存储中。

huake_00257_.jpg 以下是导致这种问题的一个示例代码:

@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() 方法来获取对象。这个方法会返回对象的最新版本,从而确保对该实体的更新能够被可靠地持久化到数据存储中。