Python 当引用表的format属性为function时,下拉列表中的web2py排序顺序
Q&A和似乎表示由IS_in_DB validator生成的下拉列表中的默认排序顺序由引用表的format属性确定。但在以下情况下,默认排序顺序是引用表的“id”:Python 当引用表的format属性为function时,下拉列表中的web2py排序顺序,python,sorting,web2py,Python,Sorting,Web2py,Q&A和似乎表示由IS_in_DB validator生成的下拉列表中的默认排序顺序由引用表的format属性确定。但在以下情况下,默认排序顺序是引用表的“id”: db.define_table('bank', Field('bank_code', 'string', unique=True, required=True, label='Bank/FI Code'), Field('bank_name', 's
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_分支的lambda函数返回的标签,它们也按其id字段排序
建议在这种情况下使用is_IN_SET,但是当lambda函数执行这种格式时,根据“format”属性进行排序的正常行为会发生什么变化 默认情况下,当IS_IN_DB validator生成一组值和相关标签时,它不会直接按生成的标签排序。相反,在数据库select中,它指定一个ORDERBY子句,其中包含用于生成标签的字段。如果引用表的format属性是Python格式字符串,则标签字段将按其显示顺序从该格式字符串中提取。在这种情况下,这具有按标签排序最终集的效果
但是,如果引用表的format属性是一个函数,则is_IN_DB不知道生成标签需要哪些字段,因此它只选择表中的所有字段,并按字段在表定义中的显示顺序对所有字段排序。在这种情况下,由于db.bank_branch.id是表定义中的第一个字段(尽管没有明确定义),因此它是ORDER BY子句中的第一个字段,导致选项按db.bank_branch表的id排序
如果要强制按生成的标签对选项进行排序,可以使用sort参数:
IS_IN_DB(db, 'bank_branch.id', db.bank_branch._format, sort=True)
另一方面,请记住,如果有许多银行分行,这种生成标签的方法会有点低效,因为format函数包含一个递归选择,即r.bank.brank_代码,它对列表中的每个项目进行单独选择。另一种方法是基于连接查询生成您自己的一组值和标签,然后使用IS_IN_set validator或使用IS_IN_DB进行验证,并单独指定表单小部件及其选项。当然,在某些情况下,可能会有更多的分支包含在选择输入中,在这种情况下,您可以使用IS_in_DB进行验证,但应该使用替代输入小部件,例如Ajax自动完成。感谢Anthony的清晰解释。我注意到的一个区别是下拉列表不是按bank_branch.bank.id排序的,而是按bank_branch.id排序的。假设id将是表定义的第一个字段,即使没有显式定义。还感谢您在使用sort=True选项时的谨慎。我的bank_branch表预计会随着时间的推移增长到大约100000条记录,递归选择最终可能会导致问题。所以这里必须遵循IS_IN_SET方法,对吗?抱歉,我们查看了错误的代码块,该ID仅在Google App Engine上从orderby中排除。我已经更正了答案。此外,如果您将有100000多条记录,那么无论如何您都不希望在表单中使用select输入,因为您将向浏览器发送所有这些记录,并且假设浏览器没有崩溃,用户将有一个超长的滚动列表。在这种情况下,您应该改为使用Ajax自动完成之类的工具,或者根据之前选择的银行等,将分支列表限制为一个子集。。