Model constraints
Often, applications need to ensure data integrity, and enforce some validations to ensure that data is complete and correct.
The PostgreSQL database manager supports many useful validations, such as avoiding duplicates, or checking that values meet certain simple conditions. Model can declare and use PostgreSQL constraints for this.
Some checks require more sophisticated logic, and are better implemented as Python code. For these cases, we can use specific model methods implementing Python constraint logic.
SQL constraints are added to the database table definition and are enforced directly by PostgreSQL. They are definedusing the
_sql_constraints class attribute.
It is a list of tuples, and each tuple has the format
(name, code, error):- name is the constraint identifier name
- code is the PostgreSQL syntax for the constraint
- error is the error message to present to users when the constraint is not verified
We will add two SQL constraints to the Book Model. One is a unique constraint ensuring that we don't have repeated books with the same title and publication date; the other is to check that the publication date is not in the future:
# class Book(models.Model):
_sql_constraints = [
('library_book_name_date_uq', # Constraint unique identifier
'UNIQUE (name, date_published)', # Constraint SQL syntax
'Book title and publication date must be unique.'), # Message
('library_book_check_date',
'CHECK (date_published <= current_date)',
'Publication date must not be in the future.'),
]
For more information on the PostgreSQL constraint syntax, see the official documentation at https://www.postgresql.org/docs/10/static/ddl-constraints.html.
Python constraints can use a piece of arbitrary code to check the conditions. The checking function should be decorated with
@api.constrains and an indication of the list of fields involved in the check. The validation is triggered when any of them is modified and will raise an exception if the condition fails.
In the case of the Library app, an obvious example is to prevent inserting incorrect ISBN numbers. We already have the logic to check that an ISBN is correct, in the
_check_isbn() method. We can use it now in a model constrain to prevent saving incorrect data:from odoo.exceptions import ValidationError
# class Book(models.Model):
@api.constrains('isbn')
def _constrain_isbn_valid(self):
for book in self:
if book.isbn and not book._check_isbn():
raise ValidationError(
'%s is an invalid ISBN' % book.isbn)
Comments
Post a Comment