Python web2py中的复合密钥

Python web2py中的复合密钥,python,web2py,composite-key,Python,Web2py,Composite Key,我在web2py中定义了一个表 db.define_table( 'pairing', Field('user',writable=True,readable=True), Field('uid', writable=True , readable=True) ) 此表需要具有唯一的用户和uid组合。我已经浏览了web2py文档,但是没有直接的方法来定义复合键。 我们如何在web2py中定义复合方式取决于您要做什么。默认情况下,web2py会自动创建一个自动递增的id字段,作为每个表的主键,这

我在web2py中定义了一个表

db.define_table(
'pairing',
Field('user',writable=True,readable=True),
Field('uid', writable=True , readable=True)
)
此表需要具有唯一的用户和uid组合。我已经浏览了web2py文档,但是没有直接的方法来定义复合键。
我们如何在web2py中定义复合方式取决于您要做什么。默认情况下,web2py会自动创建一个自动递增的
id
字段,作为每个表的主键,这是尽可能推荐的方法。如果您正在处理具有复合主键的旧数据库,并且无法更改架构,则可以指定
primarykey
属性,但有一些限制(如所述):

db.define_table(
'pairing',
Field('user',writable=True,readable=True),
Field('uid', writable=True , readable=True)
)
相反,您可能并不真正需要真正的复合主键,但您只需要某种方法来确保在表中只插入唯一的user/uid值对。在这种情况下,您可以通过为以下两个字段中的一个指定正确构造的
IS\u NOT\u In\u 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')
这将确保
uid
user
与插入的
user
的新值匹配的记录集中是唯一的(因此
user
uid
的组合必须是唯一的)。注意,只有在通过
SQLFORM
或使用
.validate\u和\u insert()
方法插入值时,才会应用验证器(例如在\u DB中的IS\u NOT\u),因此上述方法不适用于表中的任意插入,但主要用于用户输入提交


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

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

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\u uid\u md5
字段。此字段的值是从两个字段
user
uid
获得的字符串的哈希值。此字段也标记为
唯一
。因此,数据库在这里强制唯一性,这绕过了。这也适用于模拟具有两个以上字段的组合键。如果你发现这个方法有任何漏洞,请告诉我


编辑:略微更新md5哈希的计算方式,以解释下面一条评论中指出的情况。

这实际上是一个聪明的方法;然而,我决定使用内置输入验证来保持标准。这几乎是正确的。您还应考虑以下情况:
user
uid
的不同组合会产生相同的字符串,例如
user=1
uid=21
user=12
uid=1
。在这种情况下,两者都会产生
md5('121')
,并且会相互冲突。@ChenLevy,说得对。为了解释这种可能性,我稍微更新了解决方案。如果您发现任何问题,请告诉我。事实上,我认为简单地使用integer:
lambda行更有意义:((row.user我有一个表,我想在其中对另外两个字段进行验证。sh_代码和sh_组织。我尝试了使用您建议的代码,但记录仍被插入。如果没有看到您的代码,任何建议都很难说。上述方法适用于任何两个字段。