Lud*_*mer 8 python orm exception openerp odoo
我的模型中定义了一个UNIQUE约束:
class FooBar(models.Model):
_name = 'my.foobar'
# ...
_sql_constraints = [
('foo_bar_uniq', 'unique("foo", "bar")', 'You could not step twice into the same foobar!')
]
Run Code Online (Sandbox Code Playgroud)
以及一个用于创建新对象的代码的控制器:
class FooBarController(http.Controller):
@http.route('/foobar/create/', auth='public', website=True)
def create(self, foo, bar):
http.request.env['my.foobar'].create({
'foo': foo,
'bar': bar,
})
return http.request.render('my.thank_you_page')
Run Code Online (Sandbox Code Playgroud)
如果违反了UNIQUE约束,我会得到一个IntegrityError例外.我想抓住它并向用户显示不同的消息:
from psycopg2 import IntegrityError
class FooBarController(http.Controller):
@http.route('/foobar/create/', auth='public', website=True)
def create(self, foo, bar):
try:
http.request.env['my.foobar'].create({
'foo': foo,
'bar': bar,
})
return http.request.render('my.thank_you_page')
except IntegrityError:
return http.request.render('my.error_page')
Run Code Online (Sandbox Code Playgroud)
这有点......有点儿.在IntegrityError成功地抓住了,但随后的所有数据库操作(其中,因为据我所知,通过自动的触发website模块)结束InternalError:
InternalError: current transaction is aborted, commands ignored until end of transaction block.
Run Code Online (Sandbox Code Playgroud)
因此,最终用户看到的只是Internal Server Error页面.
如何正确处理UNIQUE约束违规?
这是一个扩展伊曼纽尔答案的例子:
class FooBarController(http.Controller):
@http.route('/foobar/create/', auth='public', website=True)
def create(self, foo, bar):
try:
http.request.env['my.foobar'].create({
'foo': foo,
'bar': bar,
})
return http.request.render('my.thank_you_page')
except IntegrityError:
# can't use the usual `http.request.env.cr` style,
# because `env` queries db and everything explodes
http.request._cr.rollback()
return http.request.render('my.error_page')
Run Code Online (Sandbox Code Playgroud)
您可以使用cr.savepoint() 上下文管理器:
class FooBarController(http.Controller):
@http.route('/foobar/create/', auth='public', website=True)
def create(self, foo, bar):
try:
with http.request.env.cr.savepoint():
http.request.env['my.foobar'].create({
'foo': foo,
'bar': bar,
})
return http.request.render('my.thank_you_page')
except IntegrityError:
return http.request.render('my.error_page')
Run Code Online (Sandbox Code Playgroud)
上下文管理器内的任何数据库调用都将在PostgreSQL 保存点内运行。如果发生异常,保存点(而不是事务)将被回滚,因此您将能够在当前数据库事务内进行后续调用。
此外,如果您不希望IntegrityError记录 s,您可以使用上下文管理器/装饰器暂时静音openerp.sql_db记录器(或者odoo.sql_db,如果您使用的是 Odoo 10 或更高版本) :mute_logger
from openerp.tools import mute_logger
# ...
try:
with mute_logger('openerp.sql_db'), http.request.env.cr.savepoint():
# ...
except IntegrityError:
# ...
Run Code Online (Sandbox Code Playgroud)