0

我希望为 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

从我收集到的代码__get__()中,谷歌正在使用and__set__()方法,这两种方法都将模型实例作为参数。那些可用于自定义类吗?和它的对应物有什么区别get_value_for_datastore

4

2 回答 2

2

每个模型都存在一个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]
于 2010-03-13T15:20:32.333 回答
1

如果您只想更改 ReferenceProperty 的一小部分行为,您可能需要简单地扩展它,覆盖其default_value方法。您可能会发现ReferenceProperty的来源具有指导意义。

于 2010-03-15T19:21:33.920 回答