3

我们如何function clone_entity()按照在 Python 中复制 Google App Engine 数据存储中的实体中所述使用,而无需在“编译”时知道属性名称来将值复制到不同种类的实体?(由于密钥也被复制,因此克隆发生在同一种类型中,因此上述链接中的解决方案不适用于此特定目的!)

尝试了以下(和其他变体,但无济于事)

query = db.GqlQuery("SELECT * FROM OrigKind")
results = query.fetch(10);

for user in results:
    new_entry = models.NewKind()
    new_entry_complete_key = new_entry.put()
    new_entry = clone_entity(user, Key=new_entry_complete_key)
    new_entry.put()

(需要将所有实体从OrigKind复制到NewKind

4

3 回答 3

4

您需要clone_entity的修改版本:

原始实现的答案中讨论了原始克隆方法存在一些缺陷。

def clone_entity(e, to_klass, **extra_args):
  """Clones an entity, adding or overriding constructor attributes.

  The cloned entity will have exactly the same property values as the original
  entity, except where overridden. By default it will have no parent entity or
  key name, unless supplied.

  Args:
    e: The entity to clone
    extra_args: Keyword arguments to override from the cloned entity and pass
      to the constructor.
  Returns:
    A cloned, possibly modified, copy of entity e.
  """
  klass = e.__class__
  props = dict((k, v.__get__(e, klass)) for k, v in klass.properties().iteritems())
  props.update(extra_args)
  return to_klass(**props)

# Use the clone method
query = db.GqlQuery("SELECT * FROM OrigKind")
results = query.fetch(10);

for user in results:
    new_entry = clone_entity(user, NewKind)
    new_entry.put()
于 2013-01-14T08:53:51.567 回答
2

我想在 Shay 的回答中添加几件事:

  • 处理 to_klass 没有 e 属性的情况。
  • 调整 clone_entity 方法以使用 ndb.Model

.

def clone_entity(e, to_klass, **extra_args):
    """Clones an entity, adding or overriding constructor attributes.

    The cloned entity will have exactly the same property values as the original
    entity, except where overridden or missing in to_klass. By default it will have 
    no parent entity or key name, unless supplied.

    Args:
      e: The entity to clone
      to_klass: The target class
      extra_args: Keyword arguments to override from the cloned entity and pass
        to the constructor.
    Returns:
      A cloned, possibly modified, instance of to_klass with the same properties as e.
    """
    klass = e.__class__
    props = dict((k, v.__get__(e, klass))
                 for k, v in klass._properties.iteritems()
                 if type(v) is not ndb.ComputedProperty
    )
    props.update(extra_args)
    allowed_props = to_klass._properties
    for key in props.keys():
        if key not in allowed_props:
            del props[key]
    return to_klass(**props)
于 2013-04-26T12:34:28.407 回答
1

它只是编写了一个实用程序来将实体从一个应用程序复制到另一个应用程序并压缩一种实体。该实用程序会进行精确的克隆,包括键、NDB 重复属性、serving_urls 和类型中引用的 blob。为了完成这项工作,我必须知道实体的属性类型。我使用 Python 27 和 NDB,但该实用程序也传输 db.Models。

这是查找 kind 的所有属性类型的代码:

    self.kind = 'Books'                                                    # the entities to copy
    self.model_mods = {'Books' : 'models'}                                 # modules to import the model from for a kind

    module = __import__(self.model_mods[self.kind], globals(), locals(), [self.kind], -1)
    self.model_class = getattr(module, self.kind)

    entity = self.model_class()                                            # ndb or db
    if isinstance(entity, ndb.Model): 
        self.ndb = True
        self.query = self.model_class.query()                              # prepare the query to get all the entities 
        self.makePage = self._pager(self.ndbPager)                         # wrap the ndb pager
    elif isinstance(entity, db.Model): 
        self.ndb = False
        self.query = self.model_class.all()
        self.makePage = self._pager(self.dbPager)                          # wrap the db pager
    else :
        raise ValueError('Failed to classify entities of kind : ' + str(self.kind))
    logging.info('Entities of kind : %s inherits from class : %s.Model' 
                 %(self.kind, self.ndb * 'ndb' + (not self.ndb) * 'db'))

    self.data_types = {}                                                   # create a dict of property data types                                         
    for key in self.model_class._properties :                              # the internals of the model_class object
        property_object = getattr(self.model_class, key.split('.')[0])     # strip, so it works for repeated structured properties
        self.data_types[key] = property_object.__class__.__name__          # get the property type
    logging.debug(self.data_types)

在上面的代码中,我为 db 或 NDB 包装了一个寻呼机(使用游标进行分页传输),以在 GAE appid 之间传输实体。

基于这些属性,我可以对属性进行编码和解码以传输模型。为此,我首先使用创建实体的字典NDB : entity.to_dict() or db: entity.to_dict()。我将密钥添加到字典中。现在我可以对实体的属性进行编码并腌制结果以传输编码的实体:

data = pickle.dumps(entity_dict, 1)
encoded_entity = base64.b64encode(data)  
于 2013-01-14T11:14:49.647 回答