当引用 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 自动完成)。