当引用 table 的格式属性为函数时,web2py 在下拉列表中排序
web2py sort order in dropdown when format attribute of reference table is function
Q&A and here 似乎表明 IS_IN_DB 验证器制作的下拉列表中的默认排序顺序是由引用的 table 的格式属性决定的。但在以下情况下,默认排序顺序是引用 table 的 'id':
db.define_table('bank',
Field('bank_code', 'string',
unique=True, required=True, label='Bank/FI Code'),
Field('bank_name', 'string',
required=True, label='Bank/FI Name'),
singular="Bank", plural="Banks",
format='%(bank_name)s'
)
db.bank.bank_code.requires=IS_UPPER()
db.bank.bank_name.requires=IS_UPPER()
db.define_table('bank_branch',
Field('bank', 'reference bank', label='Bank/FI'),
Field('branch_name', 'string', required=True, label='Branch Name'),
format=lambda r:'%s-%s' % (r.bank.bank_code, r.branch_name)
即使下拉标签显示 table bank_branch
的 lambda 函数返回的标签,它们也是按其 id 字段排序的。
建议 here 在这种情况下使用 IS_IN_SET,但是在 'format' 属性发生变化的基础上进行排序的正常行为的解释是什么?格式是由 lambda 函数完成的?
默认情况下,当 IS_IN_DB
验证器生成值集和相关标签时,它不会直接按生成的标签排序。相反,在数据库 select 中,它指定了一个 ORDER BY
子句,其中包含用于生成标签的字段。如果引用的 table 的 format
属性是 Python 格式字符串,则标签字段按照它们出现的顺序从该格式字符串中提取。在这种情况下,这具有按标签对最终集合进行排序的效果。
但是,如果引用的table的format
属性是一个函数,IS_IN_DB
不知道生成标签需要哪些字段,所以它只是selects table 中的所有字段和所有字段的顺序(按照它们在 table 定义中出现的顺序)。在这种情况下,因为 db.bank_branch.id
是 table 定义中的第一个字段(虽然没有明确定义),所以它是 ORDER BY
子句中的第一个字段,导致选项被排序db.bank_branch
table.
的 ID
如果你想强制选项按生成的标签排序,你可以使用sort
参数:
IS_IN_DB(db, 'bank_branch.id', db.bank_branch._format, sort=True)
顺便说一句,请记住,如果有很多银行分支机构,这种生成标签的方法效率会有些低,因为 format
函数包含递归 select(即 r.bank.brank_code
),它为列表中的每个项目执行单独的 select。另一种方法是根据连接查询生成您自己的一组值和标签,然后使用 IS_IN_SET
验证器(或仅使用 IS_IN_DB
进行验证,并分别指定表单小部件及其选项).当然,在某些时候,select 输入中包含的分支可能比合理的要多,在这种情况下,您可以使用 IS_IN_DB
进行验证,但应该使用替代输入小部件(例如,Ajax 自动完成)。
Q&A
db.define_table('bank',
Field('bank_code', 'string',
unique=True, required=True, label='Bank/FI Code'),
Field('bank_name', 'string',
required=True, label='Bank/FI Name'),
singular="Bank", plural="Banks",
format='%(bank_name)s'
)
db.bank.bank_code.requires=IS_UPPER()
db.bank.bank_name.requires=IS_UPPER()
db.define_table('bank_branch',
Field('bank', 'reference bank', label='Bank/FI'),
Field('branch_name', 'string', required=True, label='Branch Name'),
format=lambda r:'%s-%s' % (r.bank.bank_code, r.branch_name)
即使下拉标签显示 table bank_branch
的 lambda 函数返回的标签,它们也是按其 id 字段排序的。
建议 here 在这种情况下使用 IS_IN_SET,但是在 'format' 属性发生变化的基础上进行排序的正常行为的解释是什么?格式是由 lambda 函数完成的?
默认情况下,当 IS_IN_DB
验证器生成值集和相关标签时,它不会直接按生成的标签排序。相反,在数据库 select 中,它指定了一个 ORDER BY
子句,其中包含用于生成标签的字段。如果引用的 table 的 format
属性是 Python 格式字符串,则标签字段按照它们出现的顺序从该格式字符串中提取。在这种情况下,这具有按标签对最终集合进行排序的效果。
但是,如果引用的table的format
属性是一个函数,IS_IN_DB
不知道生成标签需要哪些字段,所以它只是selects table 中的所有字段和所有字段的顺序(按照它们在 table 定义中出现的顺序)。在这种情况下,因为 db.bank_branch.id
是 table 定义中的第一个字段(虽然没有明确定义),所以它是 ORDER BY
子句中的第一个字段,导致选项被排序db.bank_branch
table.
如果你想强制选项按生成的标签排序,你可以使用sort
参数:
IS_IN_DB(db, 'bank_branch.id', db.bank_branch._format, sort=True)
顺便说一句,请记住,如果有很多银行分支机构,这种生成标签的方法效率会有些低,因为 format
函数包含递归 select(即 r.bank.brank_code
),它为列表中的每个项目执行单独的 select。另一种方法是根据连接查询生成您自己的一组值和标签,然后使用 IS_IN_SET
验证器(或仅使用 IS_IN_DB
进行验证,并分别指定表单小部件及其选项).当然,在某些时候,select 输入中包含的分支可能比合理的要多,在这种情况下,您可以使用 IS_IN_DB
进行验证,但应该使用替代输入小部件(例如,Ajax 自动完成)。