在 Odoo 控制器中捕获数据唯一性约束错误
开发中经常会有的一个需求就是对数据字段做唯一性约束,在
Odoo
中为模型添加约束进行数据校验有两种方法:在 Python 程序中用@api.constrains
装饰器方法定义需要校验的字段;使用 _sql_constraints
属性添加 SQL 约束。一般来说,如果只是做唯一性约束,直接用后者即可,方便快速。当违反约束时,程序会抛出一个
psycopg2.IntegrityError
错误,在这种情况我们要对这个错误进行捕获并处理,这篇文章将以一个小例子来教你如何在 controllers 中对这个错误进行捕获,别担心,一切看起来都非常简单 :)创建模型添加约束
首先创建一个简单的用户名模型,并为其 username 字段添加唯一性约束:
from odoo import models, fields, api class MyUsername(models.Model): _name = 'my.username' _description = 'A simple username model.' username = fields.Char('Username') # Add SQL Constraints _sql_constraints = [ ('username_uniq', 'unique (username)', 'The username already exists!') ]
创建控制器
这里判断请求类型是不是 POST ,如果是则创建一条数据,否则显示提交表单的页面:
from odoo import http from psycopg2 import IntegrityError class MyUsernameController(http.Controller): @http.route('/myusername/create', type='http', auth='public', website=True) def create(self, **kwargs): if http.request.httprequest.method == 'POST': username = kwargs.get('username', None) try: http.request.env['my.username'].create({ 'username': username }) return http.request.render('my.ok', { 'username': username }) except IntegrityError: # IntegrityError handler http.request._cr.rollback() return http.request.render('my.error') return http.request.render('my.home')
创建模板
这里只是做简单的演示,只要创建一个简单的用于提交数据的表单即可,然后另外成功后我们显示提交的用户名,抛出约束错误后显示错误:
<template id="home"> <form class="oe_login_form" role="form" action="/myusername/create" method="post"> <input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/> <input type="text" name="username"/> <button type="submit" class="btn btn-default">Submit</button> </form> </template> <template id="ok"> <span>hello, <t t-esc="username"/></span> </template> <template id="error"> <span>IntegrityError!</span> </template>
到这里就已经 OK 了,安装之后打开
http://localhost:8069/myusername/create
可以看到一个输入框,输入一个名字然后提交,会显示 hello, <username>
,其中 <username>
是你输入的名字,然后再重新打开同一个链接,再次输入相同的名字提交,这次会发现抛出了错误提示 IntegrityError!
。我们在示例里捕获错误之后,简单地进行了回滚
rollback()
操作,而你在捕获错误之后应该根据需求进行相应的处理。这里要注意的是不能使用 http.request.env.cr
( 或者其他任何可能涉及数据库操作的方法和属性 ) 进行操作,因为 env
( 这些操作 ) 会对数据库进行查询操作,而在抛出错误后这一事务还没结束,是不能对数据库进行操作的。 本文采用 CC BY-NC-ND 4.0 许可协议。转载或引用时请遵守协议内容!