我試圖展示一個約800個實體的表格,並且遇到了難以保持真正緩慢的問題。 (慢15-20秒)。我成功實現了memcache,但是因爲我爲每個子實體引用了一個父模型,它仍然會導致每個800的datastore_v3.Get,並且速度很慢。如何通過預取ReferenceProperty屬性來防止過多的RPC調用?
我再實施尼克·約翰遜的ReferenceProperty prefetching並不能解決以下錯誤:
[... snipped ...]
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/myurl/mypythoncode.py", line 67, in get
prefetch_refprops(entitylist, ChildModel.parent_program.name)
File "/myurl/mypythoncode.py", line 36, in prefetch_refprops
fields = [(entity, prop) for entity in entities for prop in props]
TypeError: 'NoneType' object is not iterable
型號:
這是兩個相關機型:
class ParentModel(db.Model):
name = db.StringProperty()
# currently 109 of these
class ChildModel(db.Model):
name = db.StringProperty()
parent_program = db.ReferenceProperty(ParentModel)
website = db.StringProperty()
# currently 758 of these
的Python代碼:
在我的Python代碼中,我使用了Nick Johnson的技術efficient model memcaching和ReferenceProperty prefetching。 (我已經包括下面的ReferenceProperty預取,但不是memcaching代碼。)
class AllEntities(webapp2.RequestHandler):
def get(self):
entitylist = deserialize_entities(memcache.get("entitylist"))
entityref = prefetch_refprops(entitylist, ChildModel.parent_program.name)
if not entitylist:
entitylist = ChildModel.all().fetch(None)
entityref = prefetch_refprops(entitylist, ChildModel.parent_program.name)
memcache.set("entitylist", serialize_entities(entitylist))
context = {
'entitylist': entitylist,
}
self.response.out.write(template.render(context))
def prefetch_refprops(entities, *props):
fields = [(entity, prop) for entity in entities for prop in props]
ref_keys = [prop.get_value_for_datastore(x) for x, prop in fields]
ref_entities = dict((x.key(), x) for x in db.get(set(ref_keys)))
for (entity, prop), ref_key in zip(fields, ref_keys):
prop.__set__(entity, ref_entities[ref_key])
return entities
Jinja2的模板:
我的Jinja2模板引用迭代器 「項」,在 「entitylist」 也是parent_program
entityref = prefetch_refprops(entitylist, ChildModel.parent_program.name)
:
{% for entry in entitylist %}
<tr>
<td><a href="{{ entry.website}}">{{ entry.website }}</a></td>
<td><a href="/urlcategory/view?entityid={{ entry.parent_program.key().id() }}">{{ entry.parent_program.name }}</td>
</tr>
{% endfor %}
我已經取代了線。名稱和parent_program.key()ID()
與
entityref = prefetch_refprops(entitylist, ChildModel.parent_program)
和包括 「名稱」 和其它變型 「.KEY()。ID()」。當我使用「.key()。id()」我得到的錯誤:
AttributeError: 'ReferenceProperty' object has no attribute 'key'
我在想什麼或搞砸了?我非常感謝任何幫助!
刪除第一個'entityref = prefetch_refprops(entitylist,ChildModel.parent_program.name)'行。 'entitylist'在第一次通過時被設置爲None,所以預取失敗。 – mjibson 2012-07-15 02:13:27
謝謝,我解決了這個問題。但是現在我得到了「prefetch_refprops(companylist,ChildModel.parent_program.name)」的「AttributeError:'str'對象沒有屬性'get_value_for_datastore'」。這看起來很奇怪,因爲它實際上與Nick在他的例子中使用的完全相同。 – 2012-07-15 09:42:00
好吧,我現在修改它,將其更改爲「prefetch_refprops(companylist,ChildModel.parent_program)」。我沒有得到任何更多的錯誤,但它感覺我仍然沒有做正確的事情...... – 2012-07-15 11:03:56