在web2py中修改CRUD表单再发送到视图

1 投票
1 回答
1966 浏览
提问于 2025-04-16 02:59

我找不到办法来修改一个通过以下方式创建的表单:

from gluon.tools import Crud
crud = Crud(globals(), db)

form = crud.create(db.table_name)

因为我在表里使用了外键,所以自动生成的表单只允许输入一个整数(这个整数代表外键的主键),但我想要的是能够输入外键字段所需的任何数据类型(而不仅仅是标识符)。有没有简单的方法可以告诉 create() 函数使用外表的数据类型,而不是主表的数据类型(也就是自动递增的主键)呢?

1 个回答

3

你可以使用数据库验证器来实现这个功能。

它会显示一个选择框,里面的值来自外部表格:

(来自 http://web2py.com/book/default/chapter/07?search=requires#Database-Validators):

IS_IN_DB

考虑以下表格和需求:

db.define_table('person', Field('name', unique=True))
db.define_table('dog', Field('name'), Field('owner', db.person)
db.dog.owner.requires = IS_IN_DB(db, 'person.id', '%(name)s',
                                 zero=T('choose one'))

这个验证是在狗的插入、更新和删除表单中强制执行的。它要求狗的主人(dog.owner)必须是数据库中人员表(person.id)里的有效ID。因为有了这个验证器,狗的主人字段就变成了一个下拉框。验证器的第三个参数是一个字符串,用来描述下拉框里的元素。在这个例子中,你希望看到的是人员的名字 %(name)s,而不是人员的ID %(id)s。这里的 %(...)s 会被每条记录中对应字段的值替换。

零选项的工作方式和 IS_IN_SET 验证器非常相似。

如果你想验证这个字段,但不想要下拉框,你必须把验证器放在一个列表里。

db.dog.owner.requires = [IS_IN_DB(db, 'person.id', '%(name)s')]

验证器的第一个参数可以是数据库连接或者一个DAL集合,就像在 IS_NOT_IN_DB 中一样。

有时候你想要下拉框(所以不想使用上面的列表语法),但又想使用额外的验证器。为此,IS_IN_DB 验证器会多一个参数,这个参数可以指向其他验证器的列表,如果验证的值通过了 IS_IN_DB 的验证。例如,验证数据库中所有不在某个子集里的狗主人:

subset=db(db.person.id>100)
db.dog.owner.requires = IS_IN_DB(db, 'person.id', '%(name)s',
                                 _and=IS_NOT_IN_DB(subset,'person.id'))

IS_IN_DB 和标签

IS_IN_DB 验证器有一个可选属性 multiple=False。如果设置为 True,就可以在一个字段中存储多个值。这个字段应该是列表类型:引用,正如第六章中讨论的那样。那里有一个明确的标签示例。多个引用在创建和更新表单中会自动处理,但对DAL来说是透明的。我们强烈建议使用 jQuery 的多选插件来渲染多个字段。

撰写回答