Web2py:SQLFORM.grid:使 2 列唯一

Web2py : SQLFORM.grid : Making 2 columns unique

这是我的数据库定义:

db.define_table('emsAlertTokens',

Field('emsrelease','string',default=session.releasefield,writable=False,label=T('Release')),
            Field('emsmachine','string',default=session.machinefield,writable=False,label=T('Machine')),
            Field('emsstartdate','datetime',default=request.now,label=T('Start Date')),
            Field('emsenddate','datetime',IS_NOT_EMPTY(error_message='Please specify the End Date.'), label=T('End Date')),
            Field('errorgrepfile','upload',requires=IS_NOT_EMPTY(error_message='Please upload a valid error tokens file'),custom_store=ems_file, custom_retrieve=ems_retrieve, autodelete=True, uploadfield=True, uploadfs=None, label=T('Error Tokens')),
            Field('tokenname','string',requires=IS_NOT_EMPTY('What would you call your token file?'),label=T('Token File Name')))

您可以注意到 emsmachine 和 emsrelease 字段来自会话。我的要求是使这 2 个值的组合是唯一的。

我尝试使用以下验证器,但它不起作用。

db.emsAlertTokens.emsrelease.requires = IS_NOT_IN_DB(db(db.emsAlertTokens.emsmachine == session.machinefield), 'emsAlertTokens.emsrelease', error_message='EMS token file already exist for this release.')

即使这样也行不通:

db.emsAlertTokens.emsrelease.requires = IS_NOT_IN_DB(db(db.emsAlertTokens.emsmachine == request.vars.emsmachine), 'emsAlertTokens.emsrelease', error_message='EMS token file already exist for this release.')

请帮我解决这个问题。

验证器用于表单输入,由于这两个字段不可写(因此不是表单的一部分),验证器不会被应用(为不可写字段设置的默认值不会被验证)。

鉴于这些字段的默认值是在之前的某个时间点添加到会话中的,您应该在那个时候验证它们的联合唯一性。

另一种选择是在表单中包含预填值的字段,但包含 HTML "readonly" 属性以防止用户更改它:

Field('emsrelease', 'string', label=T('Release'),
      widget=lambda f, v: SQLFORM.widgets.string.widget(f, session.releasefield,
                                                        _readonly=True),
      requires=IS_NOT_IN_DB(db(db.emsAlertTokens.emsmachine == session.machinefield),
                            'emsAlertTokens.emsrelease',
                            error_message='EMS token file already exist for this release.')),
Field('emsmachine', 'string', label=T('Release'),
      widget=lambda f, v: SQLFORM.widgets.string.widget(f, session.machinefield,
                                                        _readonly=True))

因此,上面的方法不是使字段不可写(因此将其从表单中排除)并设置默认值,而是在小部件中预填充值并将小部件设置为 "readonly" (注意,使用这种方法,对手可以操纵表单提交的值,所以如果您担心这种可能性,您可以添加一个额外的验证器来确认提交的值与会话中的值匹配)。