在 Web2py 中使用 lambda 作为模型默认值
我尝试使用 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 看起来几乎与适用于的 lambda 几乎相同 表示在 trip_type_id 字段中,但我使用的是表 的领域。那是我做错了吗?
I'm try to use a lambda to set a default value based on a value in
another table.
Here is my model:
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']),
Locally this causes an error that says:
TypeError: <lambda>() takes exactly 1 argument (0 given)
And on my server (Linode) there is no error but when I try and create
a new trip instance with sqlform the total slots field is pre-
populated with this:
<function <lambda> at 0x7f27684b7140>
My lambda looks almost identical to the one that works fine for
represent in the trip_type_id field except I'm using the table instead
of the field. Is that what I'm doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您使用可调用(例如 lambda)作为字段默认值,我认为它不能接受任何参数。默认值用于预填充表单字段,因此它们不应依赖于记录中的其他字段值。
另一种方法是使用计算字段(尽管默认情况下它们不出现在 SQLFORM 中)。另一种选择是在表单处理阶段处理分配,可能通过 onvalidation 函数 - 类似这样:
在上面的代码中,如果提交了 Total_slots 的值,则保留该值 - 否则,将从中提取默认值Trip_type 表基于提交的 trip_type_id 的值。
更新:
如评论中所述,如果在表单中包含total_slots字段,则如果提交表单时该字段留空,则空值而不是计算值将存储在数据库。为了避免这个问题,您可以为表单指定一个 onvalidation 函数,检查 form.vars.total_slots 是否为空,如果是,则删除 form.vars.total_slots。在这种情况下,由于total_slots不会包含在DB插入中,因此将调用compute函数来填充该值。
如果您想完全避免在表单处理阶段执行任何操作,另一种选择可能是创建一个 total_slots 字段的自定义验证器。验证器的 __init__ 方法可以将 request.vars 作为参数,以便在提交表单时验证器可以使用记录的提交值。当验证器被调用时(即
__call__
方法),它可以检查total_slots的值是否为空,如果是,它可以将其替换为通过字段的compute函数计算的值。通过此设置,标准计算函数将处理直接数据库插入,验证器将通过表单处理插入。请注意,使用验证器方法时,total_slots 的值将根据 request.vars 中的值计算,这些值是验证之前提交的变量的值。在这种情况下,这应该不是问题,但更一般地说,如果任何字段验证器涉及转换,则 request.vars 中的值将与最终插入数据库记录中的值不完全匹配。
If you are using a callable (e.g., lambda) for a field default, I do not think it can take any arguments. Defaults are used to pre-populate form fields, so they should not depend on other field values in the record.
An alternative is to use a computed field (though by default they do not appear in SQLFORMs). Another option is to handle the assignment at the form processing stage, possibly via an onvalidation function -- something like this:
In the above code, if a value for total_slots is submitted, it is kept -- otherwise, a default value is pulled from the trip_type table based on the value of the submitted trip_type_id.
UPDATE:
As noted in the comments, if you include the total_slots field in the form, if the field is left blank when the form is submitted, an empty value rather than the computed value will be stored in the database. To avoid this problem, you could specify an onvalidation function for the form that checks to see if form.vars.total_slots is empty, and if it is, delete form.vars.total_slots. In that case, because total_slots will not be included in the DB insert, the compute function will be called to fill in the value.
If you want to completely avoid doing anything at the form processing stage, one other option might be to creat a custom validator for the total_slots field. The
__init__
method of the validator can take request.vars as an argument so the submitted values for the record will be available to the validator when the form is submitted. When the validator is called (i.e., the__call__
method), it can check to see if the value of total_slots is empty, and if so, it can replace it with a value computed via the field's compute function. With this setup, the standard compute function will handle direct DB inserts, and the validator will handle inserts via forms.Note, using the validator method, the value of total_slots will be computed based on the values in request.vars, which are the values of the submitted variables before validation. In this case, that shouldn't be a problem, but more generally, if any of the field validators involve transformations, the values in request.vars will not exactly match the values ultimately inserted into the DB record.