2017-09-26 108 views
0

我是web2py的新手。我正在申請文件註冊。每份文件都有一個編號,在註冊年份中是唯一的。我試圖計算字符串字段,結合數字和年份,強制執行unique=True約束。web2py獨特的約束不被強制執行

我正在使用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文檔說空值被認爲是與所有其他值不同,包括其他空值,因此添加了notnull約束,但仍允許重複。

有人可以幫忙嗎?

回答

0

最有可能你加unique=True該表最初創建。儘管DAL處理遷移,但它不會更改約束條件,如UNIQUENOT NULL - 如果要在創建表後更改這些約束,則必須通過其他工具來執行某些約束。

另外,請記住unique=True是在數據庫級別執行的,而不是表單輸入。這意味着,如果用戶提交違反約束的值,數據庫驅動程序將拋出異​​常,用戶將看到錯誤票證。相反,請考慮在提交表單時強制執行約束,可能通過onvalidation callback.process()。這樣,您可以防止將重複組合發送到數據庫並向用戶報告友好的錯誤消息。

最後,如果sr_no字段的唯一目的是強制執行唯一性約束,請考慮設置多列唯一性約束(您必須在DAL之外執行此操作,但不提供機制定義這種約束)。

+0

正確,@Anthony之後添加了「唯一」約束。我嘗試使用數據庫級別的約束,當表單級驗證代碼爲' 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 ')'給了一個錯誤票證''NoneType'對象沒有'year''屬性 –

+0

它只是'request.vars.year',而不是'request.vars.inward_date.year' 。如果以上回答您原來的問題,請隨時將其標記爲正確。 – Anthony

+0

'request.vars.year'返回當前年份,並且即使當'inward_date.year'不同時也會拋出錯誤消息。正如@Anthony所建議的,我現在已經在表單/的OnValidation函數中使用了以下代碼,而不是使用DAL。謝謝@Anthony –