Q&A here和here似乎表明IS_IN_DB验证程序在下拉列表中的默认排序顺序由引用表的format属性确定。但是在以下情况下,默认的排序顺序是被引用表的'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)
即使下拉标签显示表bank_branch
的lambda函数返回的标签,它们也会在其id字段上排序。
建议here在这种情况下使用IS_IN_SET,但是用lambda函数完成这种格式化后,基于'format'属性进行排序的正常行为又有什么解释呢?
答案 0 :(得分:1)
默认情况下,IS_IN_DB
验证器生成值集和关联的标签时,它不会直接按生成的标签进行排序。而是,在数据库选择中,它指定一个ORDER BY
子句,其中包括用于生成标签的字段。如果引用表的format
属性是Python格式的字符串,则标签字段按照显示顺序从该格式字符串中提取。在这种情况下,这具有通过标签对最终集合进行排序的效果。
但是,如果引用表的format
属性是一个函数,则IS_IN_DB
不知道生成标签需要哪些字段,因此它只是选择表中的所有字段并按以下顺序排序所有字段(按照它们在表定义中出现的顺序)。在这种情况下,由于db.bank_branch.id
是表定义中的第一个字段(尽管没有明确定义),所以它是ORDER BY
子句中的第一个字段,从而导致选项按ID的ID排序。 db.bank_branch
表。
如果要强制按生成的标签对选项进行排序,则可以使用sort
参数:
IS_IN_DB(db, 'bank_branch.id', db.bank_branch._format, sort=True)
此外,请记住,如果有许多银行分支,则这种生成标签的方法效率较低,因为format
函数包括一个递归选择(即r.bank.brank_code
),该选择为列表中的每个项目单独选择。一种替代方法是根据联接查询生成您自己的一组值和标签,然后使用IS_IN_SET
验证程序(或仅使用IS_IN_DB
进行验证,并分别指定表单小部件及其选项)。当然,在某些时候,选择输入中可能包含的分支数量可能超出合理范围,在这种情况下,您可以使用IS_IN_DB
进行验证,但应使用替代输入小部件(例如, Ajax自动完成)。