如何在web2py中的数据库级别创建多列唯一约束?

时间:2013-05-01 14:15:29

标签: web2py

如果我在models/db.py

中有类似的内容
   db.define_table('magazine', Field('name'), Field('description'))
   db.define_table('subscribe', Field('subscriber', db.auth_user), Field('magazine', db.magazine))

controller/default.py

# subscribe callback from view
@auth.requires_login()
def subscribe():
    mag_id = request.args(0, cast=int)
    db.subscribe.insert(magazine=mag_id, subscriber=auth.user.id)

用户可以点击一个订阅按钮,该按钮应该调用回调并将用户插入到他正在查看的当前杂志的订阅表中。

如何使订阅表包含订阅者和杂志的唯一组合?订阅杂志的订阅者不应该再次订阅该杂志。

例如,这应该有效:

用户1,杂志1
用户1,杂志2
用户2,杂志1

但这不应该:

用户1,杂志1
用户1,杂志1

一种解决方案是手动检查控制器中是否已存在组合:

def subscribe():
    mag_id = request.args(0, cast=int)
    subscribed = db(db.subscribe.subscriber==auth.user.id)&(db.subscribe.magazine==mag_id))

    if len(subscribed) < 1:
        # Do insert
    else:
        # Do nothing, user is already subscribed.

但是有更好的方法(最好是在数据库级别)吗?我使用IS_NOT_IN_DB()阅读可以工作,但它似乎仅限于使用表单? This thread也表明它无效。

1 个答案:

答案 0 :(得分:0)

DAL没有提供在数据库中指定多列唯一性约束的方法,但是您可以直接在web2py之外的数据库中执行此操作。但是,您可能仍希望应用程序中的某些显式代码来处理此问题 - 否则数据库级别的违规将最终生成异常。在这种情况下,您只需使用.update_or_insert()方法:

db.subscribe.update_or_insert(magazine=mag_id, subscriber=auth.user.id)

只有当该杂志和订阅者的记录不存在时,才会进行插入。