代码之家  ›  专栏  ›  技术社区  ›  noio

用缓存扩展appengine的db.property

  •  0
  • noio  · 技术社区  · 15 年前

    我正在为AppEngine实现一个属性类,非常类似于现有的 db.ReferenceProperty 。我正在实现自己的版本,因为我需要一些其他默认返回值。我的问题是,如何使属性记住其返回值,以便仅在第一次提取属性时执行数据存储查询?我所拥有的在下面,它不起作用。我读到属性类不属于实例,而是属于模型定义,所以我猜每个实例的返回值都没有缓存,而是每次都在模型上被覆盖。在哪里? 应该 我存储这个 _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
    

    编辑

    亚历克斯的回答肯定有用。但似乎内置 数据库引用属性 存储 _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 不是,所以他们怎么找到 _已解决 该方法的属性?

    编辑2

    来自 code 我猜谷歌正在使用 __get__() __set__() 方法,这两个方法都将模型实例作为参数获取。这些在自定义类中可用吗?有什么区别吗 获取数据存储的值 它的对应物呢?

    2 回复  |  直到 15 年前
        1
  •  1
  •   Nick Johnson    15 年前

    如果您只想更改referenceproperty行为的一小部分,那么可以简单地扩展它,覆盖它 default_value 方法。你可能会发现 the source 使参考属性具有指导性。

        2
  •  2
  •   Alex Martelli    15 年前

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