3

「コンパイル」時にプロパティ名を知らずにPythonでGoogle App Engineデータストアのエンティティをコピーする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にコピーする必要があります)

4

3 に答える 3

4

clone_entityの修正版が必要です:

元の実装の回答で説明されている元の clone メソッドにはいくつかの落とし穴があります。

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 に答える
1

あるappidから別のappidにエンティティをコピーし、ある種のエンティティをzipするユーティリティを作成しただけです。このユーティリティは、キー、NDBの繰り返しプロパティ、serving_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のページャー(カーソルを使用したページ転送)をラップして、GAEappid間でエンティティを転送します。

プロパティに基づいて、モデルを転送するためにプロパティをエンコードおよびデコードできます。これを行うには、最初にを使用してエンティティのdictを作成し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 に答える