使用缓存扩展appengine的db.Property

时间:2010-03-13 13:28:32

标签: python google-app-engine descriptor

我正在寻找为appengine实现一个属性类,与现有的db.ReferenceProperty非常相似。我正在实现我自己的版本,因为我想要一些其他的默认返回值。我的问题是,如何让属性记住它的返回值,以便数据存储区查询仅在第一次获取属性时执行?我所拥有的是下面的,它不起作用。我读到Property类不属于实例,而是属于模型定义,所以我猜测返回值不是为每个实例缓存,而是每次都在模型上覆盖。 的地方我存储了这个_resolved变量?

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 会在模型实例上存储_RESOLVED变量。如下所示:

[...]
    setattr(model_instance, self.__resolved_attr_name(), value)
[...]

def __resolved_attr_name(self):
    return '_RESOLVED' + self._attr_name()

get_value_for_datastore方法传递给模型实例,但make_value_from_datastore不是,所以他们如何从该方法中找到_RESOLVED属性?

编辑2

我收集的code谷歌正在使用__get__()__set__()方法,这两种方法都将模型实例作为参数。那些可用于自定义类吗?与get_value_for_datastore及其对应物有什么区别?

2 个答案:

答案 0 :(得分:2)

每个模型存在PageProperty个实例,而不是每个实体(其中实体是模型类的实例)。所以我认为你需要一个映射页面名称的字典 - >页面实体,而不是每个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]

答案 1 :(得分:1)

如果您只想更改ReferenceProperty行为的一小部分,您可能只想扩展它,覆盖其default_value方法。您可能会发现ReferenceProperty的the source具有指导性。