【发布时间】:2011-12-24 16:13:19
【问题描述】:
可以将特定列标记为 unique=true。 在 web2py 中处理多列唯一约束的最正确方法是什么?
例如,假设我有一张汇率表。它可以有从货币、到货币和汇率的列。有两行具有相同的 from 和 to 货币是没有意义的。使 from/to 组合独一无二的最优雅或正确的方法是什么?
【问题讨论】:
可以将特定列标记为 unique=true。 在 web2py 中处理多列唯一约束的最正确方法是什么?
例如,假设我有一张汇率表。它可以有从货币、到货币和汇率的列。有两行具有相同的 from 和 to 货币是没有意义的。使 from/to 组合独一无二的最优雅或正确的方法是什么?
【问题讨论】:
假设数据将通过表单输入,您可以使用表单验证器,如下所示:
db.define_table('rates',
Field('from_currency'),
Field('to_currency'))
db.rates.to_currency.requires=IS_NOT_IN_DB(
db(db.rates.from_currency==request.vars.from_currency), 'rates.to_currency')
这将确保to_currency 在from_currency 与插入的from_currency 的新值匹配的记录集中是唯一的(因此from_currency 和to_currency 的组合必须是唯一的)。
另一种选择是使用onvalidation 函数来确认这两个值是不同的——这将在通常的表单验证之后但在数据库插入之前运行。
最后,您可以改为通过 Javascript 进行客户端验证。
【讨论】:
db.executesql(...) 直接执行相关 SQL。
您也可以尝试使用Before and After callbacks。以 Anthony 的桌子为例,您可以执行以下操作:
db.rates._before_insert.append( lambda r : db( (db.rates.from_currency==r["from_currency"]) & (db.rates.to_currency==r["to_currency"]) ).select() )
如果.select() 查询返回除None 或False 之外的任何内容,它将中止当前的db.rates.insert() 并返回False。
请注意,它仍然不会创建 UNIQUE CONSTRAINT,但它比使用某些客户端验证更安全。
【讨论】: