Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a new model entity, and then read it immediately after?

My question is, what is the best way to create a new model entity, and then read it immediately after. For example,

class LeftModel(ndb.Model):
    name = ndb.StringProperty(default = "John")
    date = ndb.DateTimeProperty(auto_now_add=True)

class RightModel(ndb.Model):
    left_model = ndb.KeyProperty(kind=LeftModel)
    interesting_fact = ndb.StringProperty(default = "Nothing")

def do_this(self):
    # Create a new model entity
    new_left = LeftModel()
    new_left.name = "George"
    new_left.put()

    # Retrieve the entity just created
    current_left = LeftModel.query().filter(LeftModel.name == "George").get()

    # Create a new entity which references the entity just created and retrieved
    new_right = RightModel()
    new_right.left_model = current_left.key
    new_right.interesting_fact = "Something"
    new_right.put()

This quite often throws an exception like:

AttributeError: 'NoneType' object has no attribute 'key'

I.e. the retrieval of the new LeftModel entity was unsuccessful. I've faced this problem a few times with appengine and my solution has always been a little hacky. Usually I just put everything in a try except or a while loop until the entity is successfully retrieved. How can I ensure that the model entity is always retrieved without running the risks of infinite loops (in the case of the while loop) or messing up my code (in the case of the try except statements)?

like image 389
user714852 Avatar asked Jul 21 '12 09:07

user714852


1 Answers

Why are you trying to fetch the object via a query immediately after you have performed the put().

You should use the new_left you just created and immediately assign it to the new_right as in new_right.left_model = current_left.key

The reason you can not query immediately is because HRD uses an eventual consistency model, which means you result of the put will be visible eventualy. If you want a consistent result then you must perform ancestor queries and this implies an ancestor in the key on creation. Given you are creating a tree this is probably not practical. Have a read about Structuring Data for Strong Consistency https://developers.google.com/appengine/docs/python/datastore/structuring_for_strong_consistency

I don't see any reason why you just don't use the entity you just created without the additional query.

like image 182
Tim Hoffman Avatar answered Oct 03 '22 11:10

Tim Hoffman