2009-09-19 51 views
2

這實際上是一個python語言問題,但它包裹着Google appengine特定的問題。Google應用引擎和python以及按值傳遞的對象

我們有

 
class User(db.Model) : 
    email = db.StringProperty() 
    name = db.StringProperty() 
    password = db.StringProperty() 
    # more fields.. 

由於用戶帳戶訪問這樣的時候,我們用gaeutilities(作爲獎金問題保留一份在會議上,是這個壞在GAE?我想我會緩解db有點)

 
class UpdateProfile(webapp.RequestHandler): 
    def post(self): 
    # User posting update to his name 
    self.session = sessions.Session() 

    ####### 
    # way#1: update the copy of the User object in SESSION, then .put() it 
    self.session[ 'current_user' ].name = self.request.get('name') 
    self.session[ 'current_user' ].put() 
    # does not work. 
    ####### 

    ####### 
    # way#2: make a copy of the User object in SESSION, then .put() it 
    user = self.session[ 'current_user' ] 
    user.name = self.request.get('name') 
    user.put() 
    # works to update the datastore, but the copy of user in self.session 
    # is NOT UPDATED! I thought Python was 
    # pass-by-reference. It is when you work with lists anyway. 
    # Why isn't it "acting right" with this type of object?? 
    ####### 


    ####### 
    # way#3: way that works. 
    user = self.session[ 'current_user' ] 
    user.name = self.request.get('name') 
    user.put() 
    self.session[ 'current_user' ] = user 
    # works completely 
    ####### 

這三種情況都發生了什麼?爲什麼案例1和2沒有工作?

回答

1

對不起,我是這個網站的新手,我沒有看到評論答案的地方?

無論如何,我已經修復了煽動原帖的具體問題。雖然數據的序列化仍然不是最理想的,但是我已經設法確保將模型實體分配爲會話中的項目將按預期工作。而不是重寫序列化(將會是一個重要的重寫),而是選擇檢測何時將模型插入爲會話數據項,併爲其設置ReferenceProperty。這意味着模型對象永遠不必花費序列化的開銷。

如果與ReferenceProperty相關聯的實體被刪除,那麼當您嘗試加載它時,會話中的ReferenceProperty也會被刪除。這確實意味着你必須像Dictionary應該那樣捕獲由Session引發的異常,例如KeyError。我希望這足夠直觀,但我願意接受任何評論。我將在接下來的幾周內再次檢查此頁面。

3

我猜測:

把物體在會話意味着該對象被序列(通常酸洗)和存儲在某個地方(磁盤,存儲器,分貝)。從會話中檢索它時,將從序列化的舊狀態創建一個新的對象。

  • 在第一個例子中,每個self.session[ 'current_user' ]爲您提供了一個新的對象,其中一個更新,另一種是保存到數據庫。
  • 在第二步中,您獲取一個對象,將其保存到數據庫但不在會話中。

順便說一句,Python做「通過共享呼叫」,但是這無關你的問題;-)

+0

我認爲你可能是對的。有些奇怪的是,gaeutilities的會話支持在設置對象後立即序列化對象。在任何情況下,將該帳戶存儲到Memcache將更有意義,而不是使用會話支持。 – 2009-09-19 21:04:20

+0

Memcache(如會話)是存儲數據的地方,而不是對象。如果要更新memcache中的某些數據,則必須明確執行此操作,因此即使會話正在使用memcache,您仍然必須假定數據已序列化。 (谷歌的memcache API不保證get()的對象身份,所以你不應該假設) – 2009-09-19 21:32:14

+0

我應該澄清我以前的評論 - 在API接受「對象」作爲輸入的程度上,它存儲對象,但你應該知道它在現實中序列化它們,所以它是一個「數據」存儲。試圖從memcache中獲取數據的下一個請求理論上可能不會由同一臺服務器處理,因此您不能假定它們共享一個內存空間。 – 2009-09-19 21:36:21

2

我gaeutilities的作者。我聯繫Nick談論這個,他給了我一些好主意。我將在最終的1.3版本中爲此提供解決方案。