请有人向我解释一下self.env.cr.commit()是如何工作的,什么时候使用它,以及一些好的实践?
从Odoo文档来看,使用cr.commit似乎非常危险。这是我第一次使用它,我不知道如何在用例中正确地使用它。
编辑:
关于我的用例的更多信息:我正在通过发货提供者API创建出货量。假设我的API调用是成功的,并且我已经创建了托运,但是在处理响应过程中,由于某种原因,我必须提高UserError,并且我的更改是回滚的。因此,现在装运的状态在Odoo和运输提供者服务器上是不同的,这是不可接受的。
因此,如果我调用的方法是create_dhl_shipment(),而标志变量是True (上次调用期间发生了错误),那么我想删除最初的发货并创建一个新的。
和我的问题是:如何对数据库进行更改并防止其回滚.
在互联网搜索过程中,我偶然发现了cr.commit(),但是文档中的Odoo确实不鼓励使用它。
非常简单的例子:
Class StockPickingInherited(models.Model)
_inherit = 'stock.picking'
remnant_shipment = fields.Boolean("Possible remnant shipment")
packages = fields.One2many("stock.shipment.package", "picking_id")
def create_dhl_shipment(self):
response_from_shipping_provider = requests.get("API URL")
if response_from_shipping_provider != 200:
if not remnant_shipment:
raise UserError("Shipment creation failed")
else:
self.write({"packages" : [(5, 0, 0)]})
self.env.cr.commit() # write data into the db and keep the change from rollbacking due to raising UserError
raise UserError("Shipment creation failed")
我做得对吗?有潜在的危险吗?
发布于 2022-01-28 11:56:07
的确,self.env.cr.commit()
应该被谨慎地使用。然而,它有一些合法的用例。例如:
@api.model
def some_cron_job(self):
for record in self.env[...].search(...):
record.do_some_process()
self.env.cr.commit()
上面的内容是可以的,因为您正在对一批记录执行某些处理,并且为了避免cron作业由于其中一条记录上的错误而重复执行,您可以在处理完每条记录之后提交。(PS:使用try...except可以使上述情况更安全.或者将记录标记为“失败”,例如。这可以与commit()
一起完成)
在您的用例中,您希望向用户显示一条消息,但是您的问题是,一旦您raise
事务将回滚,因此要解决这个问题,您可以调用一个commit()
。
我也遇到过类似的情况,有时我发现使用@api.onchange
可以很好地向用户显示消息。
@api.onchange('your_field')
def onchange_your_field(self):
if self.your_field > 100:
raise UserError("Thanks for entering the field")
但是,我不再喜欢这种方法,因为Odoo已经摆脱了大多数@api.onchange
,而倾向于使用计算字段。(这一举动有很好的理由,所以也要尽量避免。)
幸运的是,在Odoo13.0版中引入了一种新的方法。
def some_method(self):
# Do something
self.write({"something" : False})
# Display message
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': title,
'message': message,
'sticky': False,
}
}
以上内容取自Odoo中的这里,如果邮件服务器凭据正确,将向用户显示一条消息。
https://stackoverflow.com/questions/70884813
复制相似问题