Как лучше всего клонировать объект NDB?

У меня есть набор сущностей с родительскими ключами и идентификаторами строк. Иногда мне нужно изменить идентификатор строки (обновить объект новым идентификатором). Из этого вопроса (Изменить идентификатор объекта Google App Engine?), похоже, мне нужно создать новую сущность и удалить старую.

Конечно, я хочу сохранить все свойства в старой сущности при создании новой, но, похоже, не существует clone метода для сущностей NDB.

Это лучший способ изменить идентификатор объекта, сохранив родительский элемент?

# clone the old_entity and parent as new_entity
new_entity = MyModel(**old_entity.to_dict(), id=new_id, parent=old_entity.parent())

И тогда я смогу сделать это, чтобы заменить старую сущность на новую:

new_entity.put()            # save the new entity
old_entity.key.delete()     # delete the old entity 

person Brent Washburne    schedule 22.10.2015    source источник
comment
Вы можете повторно опубликовать копию объекта для копирования объекта.   -  person Sanch    schedule 23.10.2015
comment
stackoverflow.com/questions/14314344/   -  person Nick Franceschina    schedule 28.10.2015


Ответы (2)


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)

пример

b = clone_entity(a, id='new_id_here')
person Sanch    schedule 23.10.2015
comment
Это не устанавливает ключ parent, не так ли? - person Brent Washburne; 23.10.2015

Ответ @sanch в большинстве случаев работает нормально, но по какой-то причине он не копирует атрибуты типа ndb.PickleProperty. Эта модификация будет работать для всех атрибутов, включая PickleProperty, а также примет необязательный параметр new_class для создания клона другого класса .:

def clone_entity(e, **extra_args):
    """
    Clone an ndb entity and return the clone.
    Special extra_args may be used to:
     - request cloned entity to be of a different class (and yet have attributes from original entity)
     - define a specific parent, id or namespace for the cloned entity.
    :param e:  The ndb entity to be cloned.
    :param extra_args: May include special args 'parent', 'id', 'namespace', that will be used when initializing new entity.
            other extra_args, may set values for specific attributes.
    :return: The cloned entity
    """

    if 'new_class' in extra_args:
        klass = extra_args.pop('new_class')
    else:
        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)
    init_args = dict()

    for arg in ['parent', 'id', 'namespace']:
        if arg in extra_args:
            init_args[arg] = extra_args.pop(arg)

    clone = klass(**init_args)
    props.update(**extra_args)
    clone.populate(**props)
    return clone
person patb    schedule 02.06.2018