I'm having trouble using get_by_id in google app engine python ndb.
Python Code
Attempt 1
resource = Content.get_by_id(6093630880088064)
resource is None
Attempt 2
resource = Content.get_by_id(6093630880088064, parent = 5249205949956096)
BadValueError: Expected Key instance, got 5249205949956096L
Attempt 3
key_parent = ndb.Key('Subject', '5249205949956096')
resource = Content.get_by_id(6093630880088064, parent = key_parent)
resource is None
Datastore
Entity Kind Content
Entity Key ahBkZXZ-YnJhaW5ib290ZWNocigLEgdTdWJqZWN0GICAgICAxKkJDAsSB0NvbnRlbnQYgICAgIDE6QoM
ID 6093630880088064
Parent ahBkZXZ-YnJhaW5ib290ZWNochQLEgdTdWJqZWN0GICAgICAxKkJDA
Subject:id=5249205949956096
Any suggestions would be greatly appreciated. My goal is that resource will be an object where I can do something like resource.name to retrieve the name property.
This problem occur when you have the key as string, the simplest solution is:
Model.get_by_id(int(id))
This problem is most likely to appear is when you read the id from url and the like:
class MyHandler(webapp2.RequestHandler):
def get(self, id):
instance = Model.get_by_id(int(id))
Solved :)
key = int(key)
key_parent = ndb.Key(Subject, 5249205949956096)
resource = Content.get_by_id(key, parent = key_parent)
Attempt 1:
You get None because no instance exists with this ID. Either the ID is wrong or it's a string not an integer like you’re passing to the function.
Attempt 2:
get_by_id actually expects the parent before the ID (if the parent is passed). If you wanna keep that order then use
resource = Content.get_by_id(id = 6093630880088064, parent = parent_key)
More importantly, the parent argument is the key of the parent not its ID.
Attempt 3:
In your code the ID of the parent is passed as a string and that of the content is passed as an integer. I'm guessing that the problem lies there. You pass either as strings of integers.
Hope that helps.
Related
It might be the most dumb question and my apologies for the same but I am confused
I have the following entity:
class Profile(ndb.Model):
name = ndb.StringProperty()
identifier = ndb.StringProperty()
pic = ndb.BlobKeyProperty() # stores the key to the profile picture blob
I want to delete the "pic" property value of the above entity so that it should look as fresh as if "pic" was never assigned any value. I do not intend to delete the complete entity. Is the below approach correct:
qry = Profile.query(Profile.identifier==identifier)
result_record_list = qry.fetch()
if result_record_list:
result_record_list[0].pic.delete() # or result_record_list[0].pic = none # or undefined or null
I am deleting the actual blob referred by this blob key separately
assign None to it and put it back to the datastore.
result_record_list[0].pic = None
result_record_list[0].put()
The datastore is an OO schemaless databse. So you can add and remove properties from the the Kind (ndb.Model) without the need of a schema update.
If you also want to cleanup the entities look at this anwser from Guido
python 2.7
app engine 1.8.5.1039
for the life of me I can't figure out whey My InventoryItem Expando model is returning None. My id is valid. I've checked the datastore more times than I'd like to remember. Do I have to pass the Expando model a parent to work properly?
class InventoryItem(db.Expando):
def toDict(self):
d = db.to_dict(self)
d['id'] = self.key().id()
return d
inventoryItem = InventoryItem(parent=toon.getInventory())
for k,v in item.iteritems():
setattr(inventoryItem,k,v)
inventoryItem.put()
inventoryItem_id = self.request.get("id")
logging.info(inventoryItem_id)#5770237022568448
item = InventoryItem.get_by_id(long(inventoryItem_id))#returns None
Your call to get_by_id will need a parent to be supplied, because you are supplying a parent when you create the entity. InventoryItem(parent=toon.getInventory())
See the call docs for get_by_id(id, parent=None, app=None, namespace=None, **ctx_options)
I would also suggest you go and read the docs on how key's work as a good understanding on what the use of parent means is pretty fundamental to using appengine.
I'm running the following code in the GAE interactive console (/_ah/admin/interactive), and I do not understand why get_by_id() returns None when the parent is not specified. The docs do not make this limitation clear and I can't think of a reason to enforce it.
import my_model
print my_model.all().fetch(1)[0].key().id() # Returns 33006, used later
print my_model.get_by_id(33006)
print my_model.get_by_id(my_model.all().fetch(1)[0].key().id())
parent = my_model.all().fetch(1)[0].parent()
print my_model.get_by_id(33006, parent=parent)
Output:
33006
None
None
<my_model object at 0x109a6a690>
db.Model definition and code showing object creation with ancestor:
class my_model(db.Model):
user_id = db.StringProperty(indexed=True)
email = db.StringProperty(indexed=True, default=None)
def create(parent):
obj = my_model(user_id='x', email='y', parent=parent)
obj.put()
The answer to your question is: because the same ID could be in another entity but with a different parent.
The IDs will be all different with the same parent or for all entities without a parent, but if there is an ancestor then your numerical IDs are not unique.
I have a python program in Google App Engine
When finding an object in the datastore when I have the key as a string, how can I do a direct read. Below is my code which is performing a loop, not good.....
class Opportunity(db.Model):
customer = db.ReferenceProperty(Customer,collection_name='opportunitys')
BNusername = db.StringProperty()
opportunity_no = db.StringProperty()
# etc etc etc.....
#BnPresets holds the object key as a string
opportunitys = Opportunity.all()
opportunitys.filter('BNusername =',BnPresets.myusername)
for oprec in opportunitys:
if str(oprec.key()) == BnPresets.recordkey:
opportunity = oprec
# I have the object here and can process etc etc
You can instantiate db.Key from string by passing it directly to the constructor:
opportunity_key = db.Key(BnPresets.recordkey)
Once you have that, simply db.get to obtain the entity identified by this key:
opportunity = db.get(opportunity_key)
I guess (by looking at the query you use) that you also want to verify the username of the object you got:
if opportunity.BNusername == BnPresets.myusername
process_opportunity(opportunity)
That should be pretty much it. The bottom line is that you should use the key first - as it uniquely identifies your entity - rather than querying for some other property and iterating through results.
Was wondering if I'm unconsciously using the Put method in my last line of code ( Please have a look). Thanks.
class User(db.Model):
name = db.StringProperty()
total_points = db.IntegerProperty()
points_activity_1 = db.IntegerProperty(default=100)
points_activity_2 = db.IntegerProperty(default=200)
def calculate_total_points(self):
self.total_points = self.points_activity_1 + self.points_activity_2
#initialize a user ( this is obviously a Put method )
User(key_name="key1",name="person1").put()
#get user by keyname
user = User.get_by_key_name("key1")
# QUESTION: is this also a Put method? It worked and updated my user entity's total points.
User.calculate_total_points(user)
While that method will certainly update the copy of the object that is in-memory, I do not see any reason to believe that the change will be persisted to the the datastore. Datastore write operations are costly, so they are not going to happen implicitly.
After running this code, use the datastore viewer to look at the copy of the object in the datastore. I think that you may find that it does not have the changed total_point value.