【问题标题】:composite key in web2pyweb2py中的复合键
【发布时间】:2012-03-13 12:00:47
【问题描述】:

我在 web2py 中定义了一个表

db.define_table(
'pairing',
Field('user',writable=True,readable=True),
Field('uid', writable=True , readable=True)
)

此表需要具有唯一的用户和 uid 组合。我查看了 web2py 文档,但没有直接的方法来定义复合键。 我们如何在 web2py 中定义复合方式

【问题讨论】:

    标签: python web2py composite-key


    【解决方案1】:

    这取决于你想要做什么。默认情况下,web2py 会自动创建一个自动递增的 id 字段作为每个表的主键,这是尽可能推荐的方法。如果您正在处理具有复合主键的旧数据库并且无法更改架构,则可以指定 primarykey 属性,但有一些限制(如 here 所述):

    db.define_table('pairing', 
        Field('user', writable=True, readable=True), 
        Field('uid', writable=True, readable=True),
        primarykey=['user', 'uid'])
    

    也许您实际上并不需要真正的复合主键,但您只需要某种方法来确保仅在表中插入唯一的用户/uid 值对。在这种情况下,您可以通过为两个字段之一指定正确构造的 IS_NOT_IN_DB 验证器来实现:

    db.define_table('pairing',
        Field('user', writable=True, readable=True),
        Field('uid', writable=True, readable=True))
    
    db.pairing.uid.requires=IS_NOT_IN_DB(db(db.pairing.user==request.vars.user),
        'pairing.uid')
    

    这将确保uiduser 与插入的user 的新值匹配的记录集中是唯一的(因此useruid 的组合必须是唯一的)。请注意,验证器(例如 IS_NOT_IN_DB)仅在通过 SQLFORM 或使用 .validate_and_insert() 方法插入值时应用,因此上述方法不适用于向表中任意插入,但主要用于用户输入提交.

    您还可以使用 SQL 对表设置多列唯一约束(您可以直接在数据库中或通过 web2py .executesql() 方法进行)。但是,即使有这样的约束,您仍然希望在应用程序中进行一些输入验证,以避免来自数据库的错误。

    【讨论】:

    • 我有一张表,我想在其中对另外两个字段进行验证。 sh_code 和 sh_organization。我尝试使用您建议的代码,但仍插入记录。任何建议
    • 很难说没有看到你的代码。上述方法适用于任意两个字段。
    【解决方案2】:

    我一直在使用计算域来创建/模拟复合键。以上述问题为例,可以如下定义联结表:

    from md5 import md5
    db.define_table( 'pairing',
                     Field('user', writable=True, readable=True),
                     Field('uid', writable=True, readable=True),
                     Field( 'user_uid_md5', 
                            length=32,
                            unique=True,
                            writable=False,
                            readable=False,
                            compute=lambda row: md5("{0}:{1}".format(row.user,row.uid)).hexdigest()))
    

    user_uid_md5 字段在插入和更新时自动计算。该字段的值是从useruid 两个字段获得的字符串的md5 哈希。该字段也标记为unique。所以数据库在这里强制执行唯一性,这可以解决Anthony 指出的限制。这也应该可以模拟具有两个以上字段的复合键。如果您发现这种方法有任何漏洞,请告诉我。

    编辑:对计算 md5 哈希的方式稍作更新,以解决Chen Levy 在下面的评论中指出的情况。

    【讨论】:

    • 这其实是一个聪明的做法;但是,我决定使用内置的输入验证来保持标准。
    • 这是几乎正确的。您还应该考虑useruid 的不同组合导致相同字符串的情况,例如user=1uid=21user=12uid=1。在这种情况下,两者都会产生md5('121'),并且会相互冲突。
    • @ChenLevy,说得好。为了解决这种可能性,我稍微更新了解决方案。如果您发现任何问题,请告诉我。
    • 实际上我认为简单地使用整数会更有意义:lambda row: ((row.user << 16) | (row.uid))。我可能是错的,但总是有机会为 2 对不同的用户/uid 获得相同的 md5。假设每个 ID 字段小于 16。
    猜你喜欢
    • 1970-01-01
    • 2012-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    相关资源
    最近更新 更多