Скопируйте объект в хранилище данных Google App Engine в Python, не зная имена свойства во время 'компиляции'

В приложении для Механизма Приложения Google Python я пишу, мне сохранили объект в хранилище данных, которое я должен получить, сделать точную копию из него (за исключением ключа) и затем отложить этот объект в.

Как я должен сделать это? В частности, есть ли любые протесты или приемы, о которых я должен знать при выполнении этого так, чтобы я получил копию вида, который я ожидаю и не что-то еще.

ETA: Ну, я испытал его, и я действительно сталкивался с проблемами. Я хотел бы сделать свою копию таким способом, которым я не должен знать названия свойств, когда я пишу код. Мои взгляды должны были сделать это:

#theThing = a particular entity we pull from the datastore with model Thing
copyThing = Thing(user = user)
for thingProperty in theThing.properties():
    copyThing.__setattr__(thingProperty[0], thingProperty[1])

Это выполняется без любых ошибок..., пока я не пытаюсь вытянуть copyThing от хранилища данных, в которой точке я обнаруживаю, что все свойства не установлены ни на Один (за исключением пользователя и ключа, очевидно). Таким образом, ясно этот код делает что-то, так как он заменяет значения по умолчанию Ни одним (всем свойствам установили значение по умолчанию), но нисколько что я хочу. Предложения?

39
задан Dan McGrath 2 September 2016 в 22:55
поделиться

2 ответа

Итак:

def clone_entity(e, **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 klass(**props)

Пример использования:

b = clone_entity(a)
c = clone_entity(a, key_name='foo')
d = clone_entity(a, parent=a.key().parent())

РЕДАКТИРОВАТЬ: Изменения при использовании NDB

Объединение комментария Гаса ниже с исправлением свойств которые указывают другое имя хранилища данных, следующий код работает для NDB:

def clone_entity(e, **extra_args):
  klass = e.__class__
  props = dict((v._code_name, v.__get__(e, klass)) for v in klass._properties.itervalues() if type(v) is not ndb.ComputedProperty)
  props.update(extra_args)
  return klass(**props)

Пример использования (примечание key_name становится id в NDB):

b = clone_entity(a, id='new_id_here')

Дополнительное примечание: см. использование _code_name , чтобы получить понятное для Python имя свойства. Без этого свойство вроде name = ndb.StringProperty ('n') вызовет в конструкторе модели ошибку AttributeError: объект типа 'foo' не имеет атрибута 'n' .

59
ответ дан 27 November 2019 в 02:18
поделиться

Я не гуру Python или AppEngine, но нельзя ли динамически получать / устанавливать свойства?

props = {}
for p in Thing.properties():
    props[p] = getattr(old_thing, p)
new_thing = Thing(**props).put()
1
ответ дан 27 November 2019 в 02:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: