在GAE数据存储的Mod中使用属性Builtin

2024-04-23 23:21:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我想制作GAE模型属性的属性。原因是在存储值之前将值转换为大写。对于一个普通的Python类,我会做如下操作:

Foo(db.Model):
    def get_attr(self):
       return self.something
    def set_attr(self, value):
       self.something = value.upper() if value != None else None
    attr = property(get_attr, set_attr)

但是,GAE数据存储有自己的属性类概念,我研究了documentation,似乎我可以重写{}来实现我的目标。然而,我不知道model_instance是什么,以及如何从中提取相应的字段。在

重写GAE属性类是提供getter/setter类功能的正确方法吗?如果是,怎么做?在

添加:

我认为重写get_value_for_datastore的一个潜在问题是,在将对象放入数据存储之前,它可能无法被调用。因此,在存储对象之前获取属性将产生不正确的值。在


Tags: 数据对象模型selfnoneget属性value
2条回答

如果您希望在一个或多个模型中有多个具有类似行为的“字段”,那么将GAE的Property类进行子类化特别有用。别担心,get_value_for_datastoremake_value_from_datastore将分别在任何存储和获取中被调用,因此如果您需要执行任何花哨的操作(包括但不限于将字符串大写,这并不是所有花哨的),在子类中重写这些方法就可以了。在

编辑:让我们看看一些示例代码(净导入和main):

class MyStringProperty(db.StringProperty):
    def get_value_for_datastore(self, model_instance):
        vv = db.StringProperty.get_value_for_datastore(self, model_instance)
        return vv.upper()

class MyModel(db.Model):
    foo = MyStringProperty()

class MainHandler(webapp.RequestHandler):

    def get(self):
        my = MyModel(foo='Hello World')
        k = my.put()
        mm = MyModel.get(k)
        s = mm.foo
        self.response.out.write('The secret word is: %r' % s)

这向您显示了字符串在数据存储中是大写的,但是如果您将get调用改为一个简单的mm = my,您将看到内存中的实例没有受到影响。在

但是,db.Property实例本身就是一个描述符,将其包装到内置的property(一个完全不同的描述符)将不能很好地与数据存储一起工作(例如,您不能基于不是db.Property的实例而是property的实例的字段名编写GQL查询,这些字段在数据存储中不是。在

因此,如果您想同时使用数据存储来处理从未实际访问过数据存储的Model的实例,则必须为逻辑上“相同”的字段选择两个名称一个是将在内存模型实例中使用的属性的名称,其中一个可以是内置的property;另一个是在数据存储中结束的属性的名称,它需要是db.Property子类的一个实例,这是您在查询中需要使用的第二个名称。当然,作为名字基础的方法需要读写第二个名字,但是你不能仅仅“隐藏”后者,因为那是数据存储中的名字,所以这个名字对查询来说是有意义的!在

你想要的是一个DerivedProperty。在那篇文章中概述了编写一个的过程-它与Alex描述的类似,但是通过重写get而不是get_value_for_数据存储,可以避免需要写入数据存储来更新它的问题。我的aetycoon库包含它和其他有用的属性。在

相关问题 更多 >