克隆NDB实体的最佳方法是什么?

时间:2015-10-22 21:03:01

标签: google-cloud-datastore app-engine-ndb google-app-engine-python

我有一组包含父键和字符串ID的实体。有时我需要更改字符串id(使用新id更新实体)。从这个问题(Modify a Google App Engine entity id?),看起来我需要创建一个新实体并删除旧实体。

当然,我想在创建新实体时保留旧实体中的所有属性,但似乎没有NDB实体的clone方法。

这是更改实体ID的最佳方式,同时保留父级吗?

# 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 

2 个答案:

答案 0 :(得分: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')

答案 1 :(得分:0)

@ sanch的答案在大多数情况下都能正常工作,但由于某种原因,它不会复制ndb.PickleProperty类型的属性。 此修改适用于所有属性,包括PickleProperty,并且还将接受optionnal 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