Copy an entity in Google App Engine datastore in Python without knowing property names at 'compile' time

后端 未结 7 913
庸人自扰
庸人自扰 2020-11-30 01:25

In a Python Google App Engine app I\'m writing, I have an entity stored in the datastore that I need to retrieve, make an exact copy of it (with the exception of the key), a

7条回答
  •  旧时难觅i
    2020-11-30 01:51

    This can be tricky if you've renamed the underlying keys for your properties... which some people opt to do instead of making mass data changes

    say you started with this:

    class Person(ndb.Model):
       fname = ndb.StringProperty()
       lname = ndb.StringProperty()
    

    then one day you really decided that it would be nicer to use first_name and last_name instead... so you do this:

    class Person(ndb.Model):
       first_name = ndb.StringProperty(name="fname")
       last_name = ndb.StringProperty(name="lname")
    

    now when you do Person._properties (or .properties() or person_instance._properties) you will get a dictionary with keys that match the underlying names (fname and lname)... but won't match the actual property names on the class... so it won't work if you put them into the constructor of a new instance, or use the .populate() method (the above examples will break)

    In NDB anyways, instances of models have ._values dictionary which is keyed by the underlying property names... and you can update it directly. I ended up with something like this:

        def clone(entity, **extra_args):
            klass = entity.__class__
            clone = klass(**extra_args)
            original_values = dict((k,v) for k,v in entity._values.iteritems() if k not in clone._values)
            clone._values.update(original_values)
            return clone
    

    This isn't really the safest way... as there are other private helper methods that do more work (like validation and conversion of computed properties by using _store_value() and _retrieve_value())... but if you're models are simple enough, and you like living on the edge :)

提交回复
热议问题