It just wrote a utility to copy enties from one appid to another and to zip entities of a kind. This utility makes an exact clone, including keys, NDB repeated properties, serving_urls and blobs referenced in the kind. To make this work I have to know the property types of the entities. I use Python 27 and NDB, but the utility also transfers db.Models.
Here is the code to find all the property types for a 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)
In the above code I wrap a pager (paged transfer using a cursor) for db or NDB to transfer the entities between the GAE appid's.
Based on the properties I can encode and decode the properties to transfer the model. To do this I first create a dict of the entities using NDB : entity.to_dict() or db: entity.to_dict()
. And I add the key to the dict. Now I can encode the properties of the entity and pickle the result to transfer the encoded entity:
data = pickle.dumps(entity_dict, 1)
encoded_entity = base64.b64encode(data)