Reputation: 146
I'm having a bit of difficulty understanding what's going on with some tasklets that I've written to use with Google App Engine's NDB datastore's asynchronous API's. The overview is: I need to pull together a purchase history for a user, and the "UserPurchase" object references the "Product" or "Custom" item that was purchased, and the "Establishment" in which it was purchased, both using KeyProperty properties in the UserPurchase ndb.Model. I want to parallelize the various NDB lookups as much as possible, so I've stuck quite close to the NDB documentation (at https://cloud.google.com/appengine/docs/standard/python/ndb/async) and built 3 tasklets:
@ndb.tasklet
def get_establishment(purch):
resto = yield purch.p_establishment.get_async()
ret = {
"rkey": resto.key.urlsafe(),
"rname": resto.resto_name
}
raise ndb.Return(ret)
@ndb.tasklet
def get_item(purch):
item = yield purch.p_item.get_async()
if (purch.p_item.kind() == "Product"):
ret = {
"ikey": item.key.urlsafe(),
"iname": item.name
}
else:
ret = {
"ikey": item.key.urlsafe(),
"iname": item.cust_name
}
raise ndb.Return(ret)
@ndb.tasklet
def load_history(purch):
at, item = yield get_establishment(purch), get_item(purch)
ret = {
"date": purch.p_datetime,
"at_key": at.rkey,
"at": at.rname,
"item_key": item.ikey,
"item": item.iname,
"qty": purch.p_quantity,
"type": purch.p_type
}
raise ndb.Return(ret)
Then, I make a call like so:
pq = UserPurchase.query().order(-UserPurchase.p_datetime)
phistory = pq.map(load_history, limit = 20)
to retrieve the most recent 20 purchases for display. When I run it, however, I get a strange exception that I'm not sure what to make of ... and I'm not familiar enough with tasklets and how they work to confidently say I know what's going on. I'd really appreciate it if someone could give me some pointers on what to look for...! Here's the exception I get when I run the above code:
...
File "/Programming/VirtualCellar/server/virtsom.py", line 2348, in get
phistory = pq.map(load_history, limit = 20)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/utils.py", line 160, in positional_wrapper
return wrapped(*args, **kwds)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/query.py", line 1190, in map
**q_options).get_result()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 383, in get_result
self.check_success()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 624, in _finish
result = [r.get_result() for r in self._results]
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 383, in get_result
self.check_success()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 430, in _help_tasklet_along
value = gen.send(val)
File "/Programming/VirtualCellar/server/virtsom.py", line 2274, in load_history
"at_key": at.rkey,
AttributeError: 'dict' object has no attribute 'rkey'
Based on the error, it almost seems like tasklets don't like returning dictionaries...
Upvotes: 1
Views: 155
Reputation: 39824
You're misinterpreting the error message: a dict is returned, but you're trying to access an attribute of that dict which doesn't exist.
It appears you want to access a value inside that dict, not an atribute of the dict, if so then change inside load_history
:
"at_key": at.rkey,
to:
"at_key": at.get('rkey'),
or:
"at_key": at['rkey'],
You also want to revisit your other similar attempts in accessing other dict values in at
and item
dicts.
Upvotes: 1