get_value_for_datastore与make_value_from_datastore的用法
2010 12 23 12:00 PM 1724次查看
分类:Google App Engine 标签:Google App Engine, Python
不过Property还有个奇怪的make_value_from_datastore方法,它的用法其实正好和get_value_for_datastore相反:后者是直接返回实体中与数据库里存储的一致的属性值,即真实存储的值是它;而前者则是在保存属性值时,对其做相应的转换,使它可以转换成datastore中适合存储的类型。(注:这里是指原始实现,你可以覆盖它以实现想要的效果。)
要理解它们,读读ReferenceProperty的源码就懂了,由于比较长,我就不列出了。
可以看到__get__和__set__会做些额外的事,在赋值时会把key设成self.__id_attr_name(),而model_instance设为self.__resolved_attr_name();取值时则尝试取self.__resolved_attr_name(),取不到再用self.__id_attr_name()作为key去访问数据库获取。
但是get_value_for_datastore就不会去访问数据库,而是直接返回self.__id_attr_name(),于是就拿到key了。
至于make_value_from_datastore,由于没有覆盖,因此是保存原值;但由于__set__已经进行了转换,因此也没差。
再来看一个更为有趣的例子,来自aetycoon的PickleProperty,稍微加了点测试代码:
import pickle
from google.appengine.ext import db
class PickleProperty(db.Property):
data_type = db.Blob
def __get__(self, model_instance, model_class):
print '__get__'
return super(PickleProperty, self).__get__(model_instance, model_class)
def __set__(self, model_instance, value):
print '__set__'
super(PickleProperty, self).__set__(model_instance, value)
def get_value_for_datastore(self, model_instance):
print 'get_value_for_datastore'
value = self.__get__(model_instance, model_instance.__class__)
if value is not None:
return db.Blob(pickle.dumps(value))
def make_value_from_datastore(self, value):
print 'make_value_from_datastore'
if value is not None:
return pickle.loads(str(value))
class Test(db.Model):
obj = PickleProperty()
def main():
print 'Content-Type: text/plain\n'
t = Test(key_name='1')
t.obj = [1, 2]
print
print t.obj
print '\nbefore put'
t.put()
print 'after put\n'
print 'before get'
t = Test.get_by_key_name('1')
print 'after get\n'
print t.obj
t.obj = '123'
print t.obj
if __name__ == '__main__':
main()
照上文所述,这个PickleProperty会在保存到数据库时,自动把属性dump成二进制值;而在获取时,又load成Python对象。而结果也证明是对的:__set__可以看到,只有和数据库交互时才会自动执行get_value_for_datastore和make_value_from_datastore,其他的访问时都是执行__get__和__set__,因此这就避免了多次转换带来的性能问题。
__set__
__get__
[1, 2]
before put
get_value_for_datastore
__get__
after put
before get
make_value_from_datastore
__set__
after get
__get__
[1, 2]
__set__
__get__
123
此外还得注意,获取数据库的实体虽然是get,但是它会设置model对象的属性,因此调用的是make_value_from_datastore和__set__;而保存实体则正好相反。
最后再来看一个JsonProperty的实现:
from django.utils import simplejson
from google.appengine.ext import db
class JsonProperty(db.TextProperty):
def validate(self, value):
return value
def get_value_for_datastore(self, model_instance):
result = super(JsonProperty, self).get_value_for_datastore(model_instance)
result = simplejson.dumps(result)
return db.Text(result)
def make_value_from_datastore(self, value):
try:
value = simplejson.loads(str(value))
except:
pass
return super(JsonProperty, self).make_value_from_datastore(value)
只是把pickle换成了simplejson而已,因此没什么需要解释的。
0条评论 你不来一发么↓