2010-02-20 16 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