我们如何使用Copy an entity in Google App Engine datastore in Python without knowing property names at 'compile' time中描述的function clone_entity()
将值复制到另一种实体中? (因为密钥也被复制,所以克隆发生在同一种类中,所以上述链接的解决方案不能用于此特定目的!)
尝试以下(以及其他变化但无效)
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 )
答案 0 :(得分:4)
您需要clone_entity的修改版本:
在原始实现的答案中讨论的original clone method存在一些缺陷。
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()
答案 1 :(得分:2)
我想在Shay的回答中添加一些内容:
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)
答案 2 :(得分:1)
它只是编写了一个实用程序,用于将enties从一个appid复制到另一个appid并压缩一种实体。此实用程序生成一个精确的克隆,包括键,NDB重复属性,serve_urls和类型中引用的blob。为了完成这项工作,我必须知道实体的属性类型。我使用Python 27和NDB,但该实用程序还传输db.Models。
以下是查找某种类型的所有属性类型的代码:
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()
创建实体的dict。我把关键词添加到词典中。现在,我可以对实体的属性进行编码,并对结果进行pickle以传输编码实体:
data = pickle.dumps(entity_dict, 1)
encoded_entity = base64.b64encode(data)