GAE将字典转换为NDB数据存储区实体

时间:2013-08-11 12:57:01

标签: python google-app-engine entity app-engine-ndb

我想问一些我正试图解决的小任务的指导方针。 我正在尝试使用JSON数据保存实体的小应用程序。

我知道你可以通过创建模型轻松地将dict转换为实体,但是,我正在尝试构建一种更通用的方法,将任何dict转换为实体。

我的步骤是:

  1. 获取字典。
  2. 通过阅读模型的类 dict ,验证dict键是否与实体模型定义相对应。
  3. 尝试在模型类构造器中解包经验证的属性(创建模型实例)
  4. 归还它。
  5. 到目前为止,我很好,但缺乏我的python知识,要么限制我,要么让我困惑。 也许我也忘记或不知道更简单的方法。

    所以就是这样:

    @classmethod
    def entity_from_dict(cls, parent_key, dict):
        valid_properties = {}
        logging.info(cls.__dict__)
        for property,value in dict.iteritems():
            if property in cls.__dict__: # should  not iterate over functions, classmethods, and @property
                logging.info(cls.__dict__[property]) # this outputs eg: StringProperty('title', required=True)
                logging.info(type(cls.__dict__[property])) #this is more interesting <class 'google.appengine.ext.ndb.model.StringProperty'>
                valid_properties.update({property: value})
        # Update the id from the dict
        if 'id' in dict: # if not creating a new entity
                valid_properties['id'] = dict['id']
        # Add the parent
        valid_properties['parent'] = parent_key
        #logging.info(valid_properties)
        try:
            entity = cls(**valid_properties)
        except Exception as e:
            logging.exception('Could not create entity \n' + repr(e))
            return False
        return entity
    

    我的问题是我只想验证ndb。属性而不是@classmethods,@ property也因为这会导致冲突。

    我也在使用expando类,因此dict中任何额外的属性都会被存储。

    如何检查这些特定类型?

2 个答案:

答案 0 :(得分:2)

解决它@Tim Hoffman建议使用Ndb模型的._properties。 我不知道的一件事是通过._properties我可以得到模型定义属性,我认为它只会返回实例属性:-)。

另外我没有使用populate,因为我发现它与在模型的构造函数中解压缩的有效dict一样; - )

所以这是:

@classmethod
def entity_from_dict(cls, parent_key, data_dict):
    valid_properties = {}
    for cls_property in cls._properties:
        if cls_property in data_dict:
            valid_properties.update({cls_property: data_dict[cls_property]})
    #logging.info(valid_properties)
    # Update the id from the data_dict
    if 'id' in data_dict: # if creating a new entity
            valid_properties['id'] = data_dict['id']
    # Add the parent
    valid_properties['parent'] = parent_key
    try:
        entity = cls(**valid_properties)
    except Exception as e:
        logging.exception('Could not create entity \n' + repr(e))
        return False
    return entity

答案 1 :(得分:1)

在将模型转换为JSON进行导出的过程中,我们使用python中的JSON转储方法将非字符串转换为字符串。因此,Jimmy Kane方法由于模型不兼容而引发错误。为避免此问题,我更新了他的方法,并添加了一个名为prop_literal的方法,该方法仅用于将封装在字符串中的非字符串字符转换为其文字类型。

我还添加了entity.put()以将实体添加到数据存储区,因为目的是:)

def prop_literal(prop_type,prop_val):
    """
    Convert non-string encapsulated in the string into literal type
    """
    if "Integer" in prop_type:
        return int(prop_val)
    elif "Float" in prop_type:
        return float(prop_val)
    elif "DateTime" in prop_type:
        # bos gecsin neticede locale
        return None
    elif ("String" in prop_type) or ("Text" in prop_type):
        return prop_val
    elif "Bool" in prop_type:
        return True if prop_val == True else False
    else:
        return prop_val


def entity_from_dict(cls, parent_key, data_dict):
    valid_properties = {}
    for cls_property in cls._properties:
        if cls_property in data_dict:
            prop_type = str(cls._properties[cls_property])
            # logging.info(prop_type)
            real_val = prop_literal(prop_type,data_dict[cls_property])
            try:

                valid_properties.update({cls_property: real_val})
            except Exception as ex:
                # logging.info("Veri aktariminda hata:"+str(ex))
        else:
            # logging.info("prop skipped")
    #logging.info(valid_properties)
    # Update the id from the data_dict
    if 'id' in data_dict: # if creating a new entity
            valid_properties['id'] = data_dict['id']
    # Add the parent
    valid_properties['parent'] = parent_key
    try:
        entity = cls(**valid_properties)
        logging.info(entity)
        entity.put()
    except Exception as e:
        logging.exception('Could not create entity \n' + repr(e))
        return False
    return entity