使用缓存扩展 appengine 的 db.Property

发布于 2024-08-25 04:38:56 字数 1407 浏览 14 评论 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

来自 code 我猜测谷歌正在使用 __get__()__set__() 方法,这两个方法都将模型实例作为参数。这些可以在自定义类中使用吗? get_value_for_datastore 及其对应项有什么区别?

I'm looking to implement a property class for appengine, very similar to the existing db.ReferenceProperty. I am implementing my own version because I want some other default return values. My question is, how do I make the property remember its returned value, so that the datastore query is only performed the first time the property is fetched? What I had is below, and it does not work. I read that the Property classes do not belong to the instances, but to the model definition, so I guess that the return value is not cached for each instance, but overwritten on the model every time. Where should I store this _resolved variable?

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

Edit

Alex' answer is certainly usable. But it seems that the built-in db.ReferenceProperty does store the _RESOLVED variable on the model instance. As evidenced by:

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

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

The get_value_for_datastore method is passed the model instance, but make_value_from_datastore is not, so how do they find the _RESOLVED property from that method?

Edit 2

From the code I gather that google is using the __get__() and __set__() methods, both of which do get the model instance as an argument. Are those usable in custom classes? What is the difference with get_value_for_datastore and its counterpart?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

撩心不撩汉 2024-09-01 04:38:56

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]

A PageProperty instance exists per-model, not per-entity (where an entity is an instance of the model class). So I think you need a dictionary that maps pagename -> Page entity, instead of a single attribute per PageProperty instance. E.g., maybe something like...:

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]
霊感 2024-09-01 04:38:56

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

If you only want to change some small part of the behaviour of ReferenceProperty, you may want to simply extend it, overriding its default_value method. You may find the source for ReferenceProperty to be instructive.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文