During method execution, it is sometimes necessary to abort the processing because an error condition was met. This recipe shows how to do this so that a helpful error message is displayed to the user when a method which writes a file to disk encounters an error.
To use this recipe, you need a method, which can have an abnormal condition. We will use the following one:
import os from openerp import models, fields, api class SomeModel(models.Model): data = fields.Text('Data') @api.multi def save(self, filename): path = os.path.join('/opt/exports', filename) with open(path, 'w') as fobj: for record in self: fobj.write(record.data) fobj.write(' ')
This method can fail because of permission issues, or a full disk, or an illegal name, which would cause an IOError
or an OSError
exception to be raised.
To display an error message to the user when an error condition is encountered, you need to take the following steps:
from openerp.exceptions import UserError
UserError
exception:@api.multi def save(self, filename): if '/' in filename or '' in filename: raise UserError('Illegal filename %s' % filename) path = os.path.join('/opt/exports', filename) try: with open(path, 'w') as fobj: for record in self: fobj.write(record.data) fobj.write(' ') except (IOError, OSError) as exc: message = 'Unable to save file: %s' % exc raise UserError(message)
When an exception is raised in Python, it propagates up the call stack until it is processed. In Odoo, the RPC layer that answers the calls made by the web client catches all exceptions and, depending on the exception class, it will trigger different possible behaviors on the web client.
Any exception not defined in openerp.exceptions
will be handled as an Internal Server Error (HTTP status 500), with the stack trace. A UserError
will display an error message in the user interface. The code of the recipe changes the
OSError
to a UserError
to ensure the message is displayed in a friendly way. In all cases, the current database transaction is rolled back.
Of course, it is not required to catch an exception with a try..except,
construct to raise a UserError
exception. It is perfectly OK to test for some condition, such as the presence of illegal characters in a filename, and to raise the exception when that test is True
. This will prevent further processing of the user request.
There are a few more exception classes defined in openerp.exceptions
, all deriving the base legacy except_orm
exception class. Most of them are only used internally, apart from the following:
Warning
: In Odoo 8.0, openerp.exceptions.Warning
played the role of UserError
in 9.0. It is now deprecated because the name was deceptive (it is an error, not a warning) and it collided with the Python built-in Warning
class. It is kept for backward compatibility only and you should use UserError
in 9.0.ValidationError
: This exception is raised when a Python constraint on a field is not respected. In Chapter 4, Application Models, refer to the Adding constraint validations to a Model recipe for more information.