我有一组包含父键和字符串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
答案 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