Python 扩展appengine';带缓存的s db.Property
我希望为appengine实现一个属性类,非常类似于现有的Python 扩展appengine';带缓存的s db.Property,python,google-app-engine,descriptor,Python,Google App Engine,Descriptor,我希望为appengine实现一个属性类,非常类似于现有的db.ReferenceProperty。我正在实现自己的版本,因为我需要一些其他默认返回值。我的问题是,如何使属性记住其返回值,以便仅在第一次获取属性时执行数据存储查询?我所拥有的就在下面,它不起作用。我读到属性类不属于实例,而是属于模型定义,因此我猜返回值不是缓存在每个实例中,而是每次都覆盖在模型上。我应该在哪里存储此\u已解析的变量 class PageProperty(db.Property): data_type = Pag
db.ReferenceProperty
。我正在实现自己的版本,因为我需要一些其他默认返回值。我的问题是,如何使属性记住其返回值,以便仅在第一次获取属性时执行数据存储查询?我所拥有的就在下面,它不起作用。我读到属性类不属于实例,而是属于模型定义,因此我猜返回值不是缓存在每个实例中,而是每次都覆盖在模型上。我应该在哪里存储此\u已解析的变量
class PageProperty(db.Property):
data_type = Page
def get_value_for_datastore(self, model_instance):
page = super(PageProperty, self).get_value_for_datastore(model_instance)
self._resolved = page
return page.key().name()
def make_value_from_datastore(self, value):
if not hasattr(self, '_resolved'):
self._resolved = Page.get_by_name(value)
return self._resolved
编辑
亚历克斯的回答当然是有用的。但是,内置的db.ReferenceProperty
似乎将\u解析的
变量存储在模型实例上。事实证明:
[...]
setattr(model_instance, self.__resolved_attr_name(), value)
[...]
def __resolved_attr_name(self):
return '_RESOLVED' + self._attr_name()
get\u value\u for_datastore
方法被传递给模型实例,但是make\u value\u from_datastore
不是,那么他们如何从该方法找到\u RESOLVED
属性呢
编辑2
据我所知,google正在使用\uuuu get\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。这些在自定义类中可用吗?_数据存储
的get_value_与其对应项有何不同?每个模型都存在一个PageProperty
实例,而不是每个实体(其中一个实体是模型类的实例)。所以我认为您需要一个映射pagename->Page实体的字典,而不是每个PageProperty实例一个属性。例如,可能类似于……:
class PageProperty(db.Property):
data_type = Page
def __init__(self, *a, **k):
super(PageProperty, self).__init__(*a, **k)
self._mycache = {}
def get_value_for_datastore(self, model_instance):
page = super(PageProperty, self).get_value_for_datastore(model_instance)
name = page.key().name()
self._mycache[name] = page
return name
def make_value_from_datastore(self, value):
if value not in self._mycache:
self._mycache[value] = Page.get_by_name(value)
return self._mycache[value]
PageProperty
实例存在于每个模型,而不是每个实体(其中实体是模型类的实例)。所以我认为您需要一个映射pagename->Page实体的字典,而不是每个PageProperty实例一个属性。例如,可能类似于……:
class PageProperty(db.Property):
data_type = Page
def __init__(self, *a, **k):
super(PageProperty, self).__init__(*a, **k)
self._mycache = {}
def get_value_for_datastore(self, model_instance):
page = super(PageProperty, self).get_value_for_datastore(model_instance)
name = page.key().name()
self._mycache[name] = page
return name
def make_value_from_datastore(self, value):
if value not in self._mycache:
self._mycache[value] = Page.get_by_name(value)
return self._mycache[value]
如果您只想更改ReferenceProperty行为的一小部分,您可能只想扩展它,覆盖它的方法。您可能会发现ReferenceProperty很有启发性。如果您只想更改ReferenceProperty行为的一小部分,您可能只想扩展它,覆盖它的方法。您可能会发现ReferenceProperty很有启发性。我以为我忽略了从属性访问实体的方法。
不,属性实例属于整个模型(这就是为什么您将其设置为类主体的一部分!),而不是每个特定实体(模型的实例),这是关键点——因此,只有属性实例才能访问特定实体。您不需要字典——只需将属性值存储在相关实体上即可。这是ReferenceProperty类采用的方法(事实上,还有其他每个属性类)。保持一个dict将导致一个不断增加的大小!我认为我忽略了从属性访问实体的方法。不,属性实例属于整个模型(这就是为什么将其设置为类主体的一部分!),而不是每个特定实体(模型的实例),这是关键点——因此,只有属性实例才能访问特定实体。您不需要字典——只需将属性值存储在相关实体上即可。这是ReferenceProperty类采用的方法(事实上,还有其他每个属性类)。保持一个dict将导致一个不断增加的大小!我希望它在找不到存储的密钥时返回一个新的实体。还有其他一些事情。关于来源。我不明白ReferenceProperty
如何在模型实例上存储\u解析的
实体,而不是像Alex解释的那样,在属性实例的dict中存储。它在传入的模型实例上使用getattr/setattr来设置/检索\ u解析的属性。您应该能够通过子类化ReferenceProperty、重写get并让它捕获db.Error来实现所需的行为。如果引发错误,请创建一个新实例、调用集并返回该实例。我希望它在找不到存储的密钥时返回其类型的新实体。还有其他一些事情。关于来源。我不明白ReferenceProperty
如何在模型实例上存储\u解析的
实体,而不是像Alex解释的那样,在属性实例的dict中存储。它在传入的模型实例上使用getattr/setattr来设置/检索\ u解析的属性。您应该能够通过子类化ReferenceProperty、重写get并让它捕获db.Error来实现所需的行为。如果引发错误,请创建新实例、调用集并返回该实例。