避免ReferenceProperty自动解引用
2010 1 16 03:15 PM 3162次查看
分类:Google App Engine 标签:Google App Engine, Python
一个模型里有一个引用属性(ReferenceProperty)。获取完实体集后,想要通过该引用属性来获取指向的实体。
重点是ReferenceProperty会自动解引用,访问它时会自动查询数据库,这样就会造成多次数据库访问,而不能用gb.get()来一次获取。
举例来说就是这样:
from google.appengine.api import apiproxy_stub_map
from google.appengine.ext import db
DB_TIME = 0
def hook(service, call, request, response):
global DB_TIME
DB_TIME += 1
print DB_TIME
apiproxy_stub_map.apiproxy.GetPreCallHooks().Append('db_hook', hook, 'datastore_v3')
class M(db.Model):
ref = db.SelfReferenceProperty()
a = M()
print 'put a'
a.put()
b = M(ref=a)
print 'put b'
b.put()
c = M(ref=b)
print 'put c'
c.put()
d = M(ref=c)
print 'put d'
d.put()
print 'start of fetching'
entites = M.all().filter('ref != ', None).fetch(3)
print 'end of fetching'
refs = [entity.ref for entity in entites]
print 'get fetching'
db.get(refs)
结果:put a其中,第6~8次访问都是entity.ref造成的。
1
put b
2
put c
3
put d
4
start of fetching
5
end of fetching
6
7
8
get fetching
Traceback (most recent call last):
#太多了,省略
BadArgumentError: Expected one of (<type 'basestring'>, <class
'google.appengine.api.datastore.Entity'>, <class
'google.appengine.api.datastore_types.Key'>); received <__main__.M
object at 0x020869D0> (a M).
实际上属性类有个get_value_for_datastore方法可以处理这个问题,只要把获取ref的那句改成这样即可:
refs = [M.ref.get_value_for_datastore(entity) for entity in entites]
结果:put a多余的数据库访问不见了,程序也不抛异常了。
1
put b
2
put c
3
put d
4
start of fetching
5
6
end of fetching
get fetching
7
最后,aetycoon里提供了一个KeyProperty,它不会自动解引用。
向下滚动可载入更多评论,或者点这里禁止自动加载。