在 Web2py 中使用 lambda 作为模型默认值

Posted

技术标签:

【中文标题】在 Web2py 中使用 lambda 作为模型默认值【英文标题】:Using a lambda for a model default in Web2py 【发布时间】:2011-11-11 15:37:45 【问题描述】:

我正在尝试使用 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 的新行程实例,总时隙字段是 pre- 用这个填充:

<function <lambda> at 0x7f27684b7140> 

我的 lambda 看起来几乎与适用于 在trip_type_id 字段中表示,但我使用的是表格 领域的。那是我做错了吗?

【问题讨论】:

【参考方案1】:

如果您使用可调用(例如 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 表中提取一个默认值。

更新:

如 cmets 中所述,如果您在表单中包含 total_slots 字段,如果在提交表单时该字段留空,则数据库中将存储一个空值而不是计算值。为避免此问题,您可以为表单指定一个 onvalidation 函数,检查 form.vars.total_slots 是否为空,如果是,则删除 form.vars.total_slots。在这种情况下,因为total_slots 不会被包含在DB insert 中,所以会调用compute 函数来填充值。

如果您想完全避免在表单处理阶段执行任何操作,另一种选择可能是为 total_slots 字段创建custom validator。验证器的__init__ 方法可以将request.vars 作为参数,因此提交的记录值将在提交表单时提供给验证器。当验证器被调用(即__call__ 方法)时,它可以检查total_slots 的值是否为空,如果是,它可以将其替换为通过字段的计算函数计算的值。使用此设置,标准计算函数将处理直接 DB 插入,而验证器将通过表单处理插入。

注意,使用验证器方法时,total_slots 的值将根据 request.vars 中的值计算,这些值是验证之前提交的变量的值。在这种情况下,这应该不是问题,但更一般地说,如果任何字段验证器涉及转换,request.vars 中的值将与最终插入数据库记录的值不完全匹配。

【讨论】:

感谢您的回答。我尝试了一个计算字段并将其显示在 SQLForm 中,但是每当我在该表单字段中输入一个值并提交时,它总是被计算字段 lambda 覆盖,即使看起来 web2py 书说它不应该。我什至在模型中尝试了 writable=true 。关于如何让它发挥作用的任何想法?由于其他限制,如果可能,我宁愿在模型级别而不是表单级别执行此操作。 如果你在表单中包含total_slots,当表单提交时,计算函数应该被忽略,即使total_slots字段是空白的。因此,如果表单字段留空,则该字段在 DB 中应为空——它不应被计算函数覆盖。

以上是关于在 Web2py 中使用 lambda 作为模型默认值的主要内容,如果未能解决你的问题,请参考以下文章

web2py 中的外键

Web开发Python实现Web服务器(web2py)

web2py官方文档翻译01

使用 lambda 而不是字符串属性名称选择模型属性

如何在 web2py 中使用模块?

web2py--------------用web2py写 django的例子 --------建立一个投票应用