2010-02-20 55 views
0

我想创建GAE模型属性的属性。原因是在存储它之前将值转换为大写的情况。对于一个普通的Python类,我会做这样的事情:在GAE数据存储的模型中使用Property Builtin

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,似乎我可以覆盖get_value_for_datastore(model_instance)达到我的目的。尽管如此,我不知道model_instance是什么,以及如何从中提取相应的字段。

重写GAE Property类是否提供getter/setter类功能的正确方法?如果是这样,该怎么办?

补充:

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

+0

啊哈,我明白了 - 'get_value_for_datastore'在对象被放到数据存储之前被称为**只是**(并且_doesn't_影响停留在内存中的实例 - 您需要从“返回”数据存储看到“受影响”的实例)。但基本上你需要做_both _... – 2010-02-20 20:31:12

回答

3

如果您希望在一个或多个模型中具有类似行为的多个“字段”,则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(一个完全不同的描述符)将不会根据现场与数据存储以及工作(例如,你可以不写GQL查询名称实际上不是db.Property的实例,而是property的实例 - 这些字段在数据存储中是而不是!)。

所以,如果你想与这两个数据存储对于从未真正到数据存储和背部的Model情况下工作,你要选择什么逻辑名称“相同的”场 - 一个是您将在内存模型实例上使用的属性的名称,并且可以是内置的property;另一个是最终在数据存储区中的属性的名称,并且需要成为db.Property子类的实例,这是您需要在查询中使用的第二个名称。当然,名字背后的方法需要读写第二个名字,但是你不能只隐藏后一个名字,因为这是数据存储中的名字,所以这个名字对于查询!

+0

我试图扩展StringProperty与get_value_for_datastore重写,但我似乎没有做任何事情。这是为什么? – ejel 2010-02-20 18:44:05

+0

忽略我上面的评论,那是我的不好。重写StringProperty确实有效。但是,正如我担心的那样,只有在对象被放入数据存储库后才会调用它。我想要有一种像普通制定者一样总是能够控制的方法。 – ejel 2010-02-20 19:21:29

+0

“Overriding StringProperty”是一个很奇怪的短语 - 我正在谈论的是子类“Property”(不是任何现有的具体子类)和重写'get_value_from_datastore'和'make_value_from_datastore'(它们是**方法**,_not_ **类** - “重写”一个类本质上是无稽之谈)。你能向我们展示一个你想通过这个奇怪的“重写StringProperty”短语进行交流的代码示例,以及观察到的行为会导致你相信它不像记录中那样工作? – 2010-02-20 20:04:08

1

你想要的是一个DerivedProperty。写这篇文章的过程就是在这篇文章中描述的 - 它与Alex所描述的类似,但通过覆盖得到而不是get_value_for_datastore,可以避免需要写入数据存储以更新它的问题。我的aetycoon库有它和其他有用的属性。

+0

你的建议似乎是一个很好的解决方案。但是,这样做,我仍然需要有两个属性,原始的和衍生的小写属性,对吗?我仍然犹豫有两个属性,因为我需要的属性是小写(我不关心原始字符串)。 – ejel 2010-02-27 02:40:28

+1

这是正确的。不过,您不需要两个属性名称即可访问较小型的版本。如果你不关心原始字符串,你可以在输入时小写,然后以这种方式存储它。 – 2010-02-27 12:20:28

+0

是的,我不在乎原来的字符串。但是,即使我可以对输入进行较低层次的处理,但我更愿意在数据层执行以控制数据一致性。 – ejel 2010-02-27 21:06:09