【问题标题】:web2py unique constraint not being enforced未强制执行 web2py 唯一约束
【发布时间】:2018-03-07 07:37:09
【问题描述】:

我是 web2py 的新手。我正在申请文件注册。每个文件都分配有一个编号,该编号在注册年份是唯一的。我试图有一个计算字符串字段,结合数字和年份,强制执行unique=True 约束。

我正在使用 SQLite,web2py 默认数据库。我的表定义:

db.define_table('doc_master_new',
            Field('sr_no', 'string', unique=True, notnull=True,
                  compute=lambda r: str(r['inward_no']) + '/' + str(r['inward_date'].year)),
            Field('inward_no', 'integer'),
            Field('inward_date', 'date', default=request.now),
            Field('doc_date', 'date'),
            Field('doc_type', db.doc_type, requires=IS_IN_DB(db, db.doc_type, '%(type_code)s', orderby=db.doc_type.id)),
            Field('applicant_type'),  ## creditor/borrower/third-party
            Field('no_defect', 'boolean', default=False),
            Field('time_stamp', 'datetime', default=request.now)
           )

和控制器:

def add_doc():    
db.doc_master_new.sr_no.writable = False
db.doc_master_new.sr_no.readable = False
db.doc_master_new.time_stamp.writable = False
db.doc_master_new.time_stamp.readable = False
db.doc_master_new.no_defect.writable = False
db.doc_master_new.no_defect.readable = False
form = SQLFORM(db.doc_master_new,
              labels = { 'inward_no':'SR No',
                        'inward_date':'SR Date',
                        'doc_date':'Document Date',
                        'doc_type':'Document Type',
                       }
              )
if form.process().accepted:
    session.flash = 'Document Added'
    redirect(URL('index_n'))
return locals()

唯一约束没有被强制执行,并且相同的值被插入到表中。我不明白为什么。 SQLite 文档说 NULL 值被认为与所有其他值(包括其他 NULL)不同,因此添加了 notnull 约束,但仍然允许重复。

有人可以帮忙吗?

【问题讨论】:

    标签: sqlite web2py


    【解决方案1】:

    您很可能在最初创建表之后添加了unique=True。尽管 DAL 处理迁移,但它不会更改约束,例如 UNIQUENOT NULL - 如果您想在创建表后更改这些约束,则必须通过其他工具进行一些操作。

    另外,请记住 unique=True 在数据库级别强制执行,而不是表单输入。这意味着如果用户提交违反约束的值,数据库驱动程序将抛出异​​常并且用户将看到错误票证。相反,考虑在表单提交时强制执行约束,可能通过.process()onvalidation callback。这样,您可以防止将重复的组合发送到数据库并向用户报告友好的错误消息。

    最后,如果 sr_no 字段的唯一目的是强制唯一性约束,请考虑改为设置多列唯一性约束(您必须在 DAL 之外执行此操作,它不提供机制用于定义此类约束)。

    【讨论】:

    • 正确,@Anthony,后来添加了unique 约束。当表单级验证代码 db.doc_master_new.inward_no.requires = IS_NOT_IN_DB(db(db.doc_master_new.inward_date.year == request.vars.inward_date.year), 'doc_master_new.inward_no' 时,我尝试使用数据库级约束)` 给出了错误票 <type 'exceptions.AttributeError'> 'NoneType' object has no attribute 'year'
    • 只是request.vars.year,而不是request.vars.inward_date.year。如果以上回答了您的原始问题,请随时将其标记为正确。
    • request.vars.year 返回当前年份,即使inward_date.year 不同,也会抛出错误消息。正如@Anthony 建议的那样,我现在没有使用 DAL,而是在表单 / 的 OnValidation 函数中使用了以下代码。谢谢@Anthony
    • 对不起,我以为是表名和字段名。问题是 request.vars.inward_date 是一个字符串,而不是 datetime 对象。您可以通过int(request.vars.inward_date[:4])datetime.datetime.strptime(request.vars.inward_date[:10], '%Y-%m-%d').year 获得年份。另外,在查询中,它应该是db.doc_master_new.inward_date.year(),而不是db.doc_master_new.inward_date.year
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-06
    • 1970-01-01
    相关资源
    最近更新 更多