2011-09-06 8 views
3

我嘗試使用lambda來根據另一個表中的值 中的值設置默認值。在Web2py中使用lambda作爲默認模型

這裏是我的模型:

db.define_table('trip_instance', timestamp, sos_table, 
    Field('trip_type_id', db.trip_type, label='Trip Type', 
     widget=trip_select_widget, requires = IS_IN_DB(db, 'trip_type.id', '% 
     (name)s'), represent=lambda id:db.trip_type(id)['name']), 
    Field('total_slots', 'integer', default=lambda r: 
     db.trip_type(r.trip_type_id)['total_slots']), 

本地這將導致一個錯誤,指出:

TypeError: <lambda>() takes exactly 1 argument (0 given) 

而且我的服務器上(的Linode)沒有錯誤,但是當我嘗試創建 一個新的旅行實例與sqlform總插槽字段是前 填充此:

<function <lambda> at 0x7f27684b7140> 

我的lambda看起來幾乎和 工作正常的一樣,它代表trip_type_id字段,除了我使用字段的表而不是 。這是我做錯了什麼?

回答

3

如果您使用可調用的(例如,lambda)作爲字段默認值,我不認爲它可以接受任何參數。默認值用於預填充表單域,所以它們不應該依賴記錄中的其他域值。

另一種方法是使用computed field(儘管默認情況下它們不出現在SQLFORM中)。另一種選擇是在表單處理階段來處理任務,可能經由一個onvalidation功能 - 是這樣的:

form.accepts(...,onvalidation=lambda form:form.vars.update(
    total_slots=form.vars.total_slots or 
    db.trip_type(form.vars.trip_type_id)['total_slots'])) 

在上面的代碼中,如果對於一個total_slots值被提交時,它被保持 - 否則,根據提交的trip_type_id的值從trip_type表中提取默認值。

UPDATE:

正如在評論中指出,如果包括在形式total_slots場,如果該字段留空,則提交表單時,一個空值,而不是計算值將是存儲在數據庫中。爲了避免這個問題,你可以指定一個窗體的onvalidation函數來檢查form.vars.total_slots是否爲空,如果是,則刪除form.vars.total_slots。在這種情況下,因爲total_slots不會包含在DB插入中,所以會調用compute函數來填充值。

如果您想完全避免在表單處理階段執行任何操作,可以使用其他選項爲total_slots字段創建一個custom validator。驗證器的__init__方法可以將request.vars作爲參數,以便提交表單時提交的記錄值將被驗證器使用。當調用驗證程序(即__call__方法)時,它可以檢查total_slots的值是否爲空,如果是,則可以用通過字段的計算函數計算的值替換它。通過這種設置,標準計算函數將處理直接的數據庫插入,驗證器將通過表單處理插入。

請注意,使用驗證器方法,total_slots的值將根據request.vars中的值進行計算,這些值是驗證前提交的變量的值。在這種情況下,這應該不是問題,但更一般地說,如果任何字段驗證程序涉及轉換,則request.vars中的值不會完全匹配最終插入到數據庫記錄中的值。

+0

感謝您的回答。我嘗試了一個計算字段,並將其顯示在SQLForm中,但每當我在該表單字段中輸入一個值並提交時,它總是被計算字段lambda覆蓋,儘管它出現web2py書中說它不應該。我甚至在模型中嘗試了writable = true。任何想法如何讓這個工作?由於其他限制,我寧願在模型級別上執行此操作,而不是在可能的情況下執行表單級別。 – LennonR

+0

如果在表單中包含total_slots,則在提交表單時,即使total_slots字段留空,計算函數也應該被忽略。因此,如果表單域保留爲空,則該字段在數據庫中最終應該爲空 - 它不應被計算函數覆蓋。 – Anthony

相關問題