Odoo ORM Advanced

Các trường nâng cao

Trường Binary

Trường Binary thường được sử dụng để lưu các tệp tin, ảnh vào database.

Tham số:

  1. attachment (bool): mặc định là True, quy định trường này sẽ được lưu trong bảng ir_attachment hay trong một cột của model.

  2. prefetch (bool): mặc định là False, quy định trường này không được tìm nạp trước.

  3. _depends_context = ('bin_size',): phụ thuộc vào ngữ cảnh (nội dung hoặc kích thước).

Ví dụ:

class Student(models.Model)
    _name = 'education.student'

    avatar = fields.Binary(string='Avatar')

Trường Html

Trường Html được dùng để đóng gói nội dung mã html.

Tham số:

  1. sanitize (bool): giá trị phải được làm sạch hay không (mặc định: True).

  2. sanitize_tags (bool): có làm sạch thẻ hay không (chỉ một danh sách trắng các thuộc tính được chấp nhận, mặc định: True).

  3. sanitize_attributes (bool): có làm sạch các thuộc tính hay không (chỉ một danh sách trắng các thuộc tính được chấp nhận, mặc định: True).

  4. sanitize_style (bool): có làm sạch các kiểu thuộc tính hay không (mặc định: False).

  5. strip_style (bool): có loại bỏ các kiểu thuộc tính hay không (đã xóa và do đó không được làm sạch, mặc định: False).

  6. strip_classes (bool): có loại bỏ các thuộc tính của lớp hay không (mặc định: False).

Ví dụ:

class Student(models.Model)
    _name = 'education.student'

    introduce_yourself = fields.Html(string='Introduce Yourself')

Trường Image

Trường Image dùng để đóng gói một hình ảnh, được mở rộng từ trường Binary. Nếu kích thước hình ảnh lớn hơn giới hạn max_width/max_height của pixel, hình ảnh sẽ được thay đổi kích thước thành giới hạn bằng cách giữ nguyên tỷ lệ khung hình.

Tham số:
  1. max_width (int): chiều rộng tối đa của hình ảnh (mặc định: 0, không giới hạn).

  2. max_height (int): chiều cao tối đa của hình ảnh (mặc định: 0, không giới hạn).

  3. verify_resolution (bool): có nên xác minh độ phân giải hình ảnh để đảm bảo nó không vượt quá. Độ phân giải hình ảnh tối đa hay không (mặc định: True). Xem odoo.tools.image.ImageProcess để biết độ phân giải hình ảnh tối đa (mặc định: 45e6).

Ghi chú

Nếu không có max_width/max_height nào được chỉ định (hoặc được đặt thành 0) và verify_resolutionFalse, thì nội dung trường sẽ hoàn toàn không được xác minh và phải sử dụng trường Binary.

Ví dụ:

class Class(models.Model)
    _name = 'education.class'

    image_128 = fields.Image(string='Logo', max_width=128, max_height=128)

Trường Monetary

Đóng gói một float được biểu thị bằng một loại tiền tệ res_currency nhất định. Độ chính xác thập phân và ký hiệu tiền tệ được lấy từ thuộc tính currency_field.

Tham số:
  1. currency_field (str): trường tiền tệ này được thể hiện bằng tên của trường Many2one chứa res_currency (mặc định: currency_id)

Ví dụ:

class Class(models.Model)
    _name = 'education.class'

    currency_id = fields.Many2one('res.currency', string='Currency')
    class_fund = fields.Monetary(string='Class Fund', currency_field='currency_id')

Trường Selection

Đóng gói một sự lựa chọn duy nhất giữa các giá trị khác nhau.

Tham số:
  1. selection (list(tuple(str,str)) hoặc được gọi hoặc str): chỉ định các giá trị có thể cho trường này. Nó được đưa ra dưới dạng danh sách các cặp (giá trị, nhãn) hoặc phương thức của model hoặc tên phương thức.

  2. selection_add (list(tuple(str,str)): cung cấp phần mở rộng của lựa chọn trong trường hợp trường bị ghi đè. Nó là một danh sách các cặp (giá trị, nhãn) hoặc các đơn lẻ (giá trị,), trong đó các giá trị duy nhất phải xuất hiện trong vùng chọn được ghi đè. Các giá trị mới được chèn theo thứ tự phù hợp với lựa chọn được ghi đè theo ví dụ dưới đây.

    selection = [('a', 'A'), ('b', 'B')]
    selection_add = [('c', 'C'), ('b',)]
    > result = [('a', 'A'), ('c', 'C'), ('b', 'B')]
    
  3. ondelete: cung cấp một cơ chế dự phòng cho bất kỳ trường nào bị ghi đè với select_add. Nó là một dict ánh xạ các tùy chọn từ select_add đến một hành động dự phòng. Hành động dự phòng này sẽ được áp dụng cho tất cả các bản ghi có tùy chọn select_add ánh xạ tới nó.

  4. Những hành động có thể là một trong số thuộc tính dưới đây:
    • set null: mặc định, tất cả các bản ghi có tùy chọn này sẽ đặt giá trị lựa chọn thành False.

    • cascade: tất cả các bản ghi có tùy chọn này sẽ bị xóa cùng với tùy chọn đó.

    • set default: tất cả những bản ghi với lựa chọn này sẽ được cài đặt mặc định của định nghĩa trường.

    • callable: callable có đối số đầu tiên và duy nhất là tập hợp các bản ghi chứa lựa chọn của Selection để xử lý tùy chỉnh.

Thuộc tính selection là bắt buộc ngoại trừ trường hợp related hoặc các trường mở rộng.

Trường Text

Tương tự như trường Char nhưng được sử dụng cho nội dung dài hơn, không có kích thước và thường được hiển thị dưới dạng hộp văn bản nhiều dòng.

Tham số:
  1. translate (bool or callable): cho phép dịch các giá trị của trường; sử dụng translate = True để dịch toàn bộ các giá trị của trường; translate cũng có thể là một hàm có thể gọi để translate(callback, value) dịch giá trị bằng cách sử dụng lệnh callback(term) để truy xuất bản dịch của các thuật ngữ.

Ví dụ:

class Student(models.Model)
    _name = 'education.student'

    name = fields.Html(string='Name', translate=True)

Các trường Date(time)

DateDatetime là những trường rất quan trọng trong bất kỳ ứng dụng nào. Việc sử dụng sai mục đích của chúng có thể tạo ra các lỗi vô hình nhưng gây khó chịu. Phần này sẽ cung cấp cho các nhà phát triển Odoo kiến thức cần thiết để tránh sử dụng sai các trường này. Khi gán giá trị cho trường Date/Datetime, các tùy chọn sau là hợp lệ:

  • Một đối tượng Date hoặc Datetime.

  • Một chuỗi ở định dạng máy chủ thích hợp:

    • YYYY-MM-DD cho các trường Date.

    • YYYY-MM-DD HH:MM:SS cho các trường Datetime.

  • False hoặc None.

Lớp DateDatetime có hỗ trợ các phương thức để chuyển đổi kiểu dữ liệu:

  • to_date() sẽ chuyển đổi thành datetime.date.

  • to_datetime() sẽ chuyển đổi thành datetime.datetime.

Ví dụ

Phân tích cú pháp ngày/giờ đến từ các nguồn bên ngoài:

fields.Date.to_date(self._context.get('date_from'))

Các phương pháp so sánh Ngày/Giờ:

  • Trường Date chỉ có thể được so sánh với các đối tượng Date.

  • Trường Datetime chỉ có thể được so sánh với các đối tượng Datetime.

Cảnh báo

Các chuỗi đại diện cho DateDatetime có thể được so sánh với nhau, tuy nhiên kết quả có thể không phải là kết quả mong đợi, vì chuỗi Datetime sẽ luôn lớn hơn chuỗi Date, do đó phương pháp này không được khuyến khích.

Các phép toán phổ biến với ngày và giờ như cộng, trừ hoặc tìm nạp đầu/cuối của một khoảng thời gian được hiển thị thông qua cả hai DateDatetime. Những trợ giúp này cũng có sẵn bằng cách nhập odoo.tools.date_utils.

Ghi chú

Múi giờ

Các trường Datetime được lưu trữ dưới dạng cột timestamp without timezone trong database và được lưu trữ trong múi giờ UTC. Đây là do thiết kế, vì nó làm cho database Odoo độc lập với múi giờ của hệ thống máy chủ lưu trữ. Chuyển đổi múi giờ hoàn toàn do phía khách hàng quản lý.

Trường Date

Đóng gói một đối tượng ngày tháng.

class Student(models.Model)
    _name = 'education.student'

    date_of_birth = fields.Date(string='Date of birth')
  1. static add (value, *args, **kwargs)

    Trả về tổng của value và a relativedelta.

    Tham số:

    1. value: ngày tháng hoặc ngày giờ bắt đầu.

    2. args: vị trí đối số chuyển đến relativedelta.

    3. kwargs: từ khóa đối số chuyển đến relativedelta.

    Return: trả về date/datetime

  2. static context_today (record, timestamp=None)

    Trả lại ngày hiện tại như đã ghi nhận trong múi giờ của khách hàng ở định dạng phù hợp với các trường ngày.

    Ghi chú

    Phương pháp này có thể được sử dụng để tính toán các giá trị mặc định.

    Tham số:
    1. record: bản ghi mà từ đó múi giờ được lấy.

    2. timestamp (datetime): giá trị ngày giờ tùy chọn để sử dụng thay cho ngày và giờ hiện tại (phải là ngày giờ, không thể chuyển đổi ngày thông thường giữa các múi giờ).

    Return type: Date

  3. static end_of (value, granularity)

    Kết thúc một khoảng thời gian kể từ ngày một ngày hoặc một ngày giờ.

    Tham số:
    1. value: ngày ban đầu hoặc ngày giờ.

    2. granularity: Loại khoảng thời gian trong chuỗi, có thể là năm, quý, tháng, tuần, ngày hoặc giờ.

    Return: Một đối tượng date/datetime tương ứng với thời điểm bắt đầu của khoảng thời gian được chỉ định.

  4. static start_of (value, granularity)

    Bắt đầu một khoảng thời gian từ một ngày hoặc một ngày giờ.

    Tham số:
    1. value: ngày ban đầu hoặc ngày giờ.

    2. granularity: Loại khoảng thời gian trong chuỗi, có thể là năm, quý, tháng, tuần, ngày hoặc giờ.

    Return: Một đối tượng date/datetime tương ứng với thời điểm bắt đầu của khoảng thời gian được chỉ định.

  5. static subtract (value, *args, **kwargs)

    Trả về sự khác biệt giữa value và a relativedelta.

    Tham số:

    1. value: ngày ban đầu hoặc ngày giờ.

    2. args: vị trí đối số chuyển đến relativedelta.

    3. kwargs: từ khóa đối số chuyển đến relativedelta.

    Return: trả về date/datetime

  6. static to_date (value)

    Chuyển đổi value thành một đối tượng date.

    Cảnh báo

    Nếu một đối tượng datetime được cung cấp dưới dạng giá trị, nó sẽ được chuyển đổi thành một đối tượng date và tất cả thông tin cụ thể về datetime sẽ bị mất (HMS, TZ,…).

    Tham số: value (str hoặc date hoặc datetime): Giá trị cần chuyển đổi.

    Return: một đối tượng đại diện value.

    Return type: date hoặc False.

  7. static to_string (value)

    Chuyển đổi một đối tượng date hoặc datetime sang chuỗi.

    Tham số: value: Giá trị cần chuyển đổi.

    Return: một chuỗi đại diện value ở định dạng ngày của máy chủ, nếu value là loại datetime thì giờ, phút, giây, tzinfo sẽ bị cắt bớt.

    Return type: str

  8. static today (*args)

    Trả về ngày hiện tại ở định dạng mà ORM mong đợi.

    Ghi chú

    Hàm này có thể được sử dụng để tính toán các giá trị mặc định.

Trường Datetime

Đóng gói một đối tượng datetime trong python.
class Student(models.Model)
    _name = 'education.class'

    attendance_time_start = fields.Datetime(string='Attendance time start')
  1. static add (value, *args, **kwargs)

    Trả về tổng của value và a relativedelta.

    Tham số:

    1. value: ngày tháng hoặc ngày giờ bắt đầu.

    2. args: vị trí đối số chuyển đến relativedelta.

    3. kwargs: từ khóa đối số chuyển đến relativedelta.

    Return: trả về kết quả date/datetime

  2. static context_timestamp (record, timestamp)

    Trả lại timestamp đã được chuyển đổi thành múi giờ của khách hàng.

    Ghi chú

    Phương thức này không được sử dụng như một trình khởi tạo mặc định, vì các trường datetime được tự động chuyển đổi khi hiển thị ở phía máy khách. Đối với các giá trị mặc định nên sử dụng hàm now().

    Tham số:

    1. record: bản ghi mà từ đó múi giờ sẽ được lấy.

    2. timestamp (datetime): giá trị ngày giờ được biểu thị bằng UTC sẽ được chuyển đổi sang múi giờ ứng dụng khách.

    Return: timestamp được chuyển đổi thành ngày giờ trong múi giờ ngữ cảnh. Return type: datetime

  3. static end_of (value, granularity)

    Kết thúc một khoảng thời gian kể từ ngày một ngày hoặc một ngày giờ

    Tham số:
    1. value: ngày ban đầu hoặc ngày giờ.

    2. granularity: Loại khoảng thời gian trong chuỗi, có thể là năm, quý, tháng, tuần, ngày hoặc giờ.

    Return: Một đối tượng date/datetime tương ứng với thời điểm bắt đầu của khoảng thời gian được chỉ định.

  4. static start_of (value, granularity)

    Bắt đầu một khoảng thời gian từ một ngày hoặc một ngày giờ.

    Tham số:
    1. value: ngày ban đầu hoặc ngày giờ.

    2. granularity: Loại khoảng thời gian trong chuỗi, có thể là năm, quý, tháng, tuần, ngày hoặc giờ.

    Return: Một đối tượng date/datetime tương ứng với thời điểm bắt đầu của khoảng thời gian được chỉ định.

  5. static now (* args)

    Trả về ngày và giờ hiện tại ở định dạng mà ORM mong đợi.

    Ghi chú

    Hàm này có thể được sử dụng để điền các giá trị mặc định.

  6. static subtract (value, *args, **kwargs)

    Trả về sự khác biệt giữa value và a relativedelta.

    Tham số:

    1. value: ngày ban đầu hoặc ngày giờ.

    2. args: vị trí đối số chuyển đến relativedelta.

    3. kwargs: từ khóa đối số chuyển đến relativedelta.

    Return: trả về date/datetime

  7. static to_datetime (value)

    Chuyển ORM value thành một giá trị datetime.

    Tham số:

    1. value (str hoặc date hoặc datetime): ngày ban đầu hoặc ngày giờ.

    Return: một đối tượng đại diện value. Return type: datetime hoặc None.

  8. static to_string (value)

    Chuyển đổi một đối tượng date hoặc datetime sang chuỗi.

    Tham số: value: Giá trị cần chuyển đổi

    Return: một chuỗi đại diện value ở định dạng ngày của máy chủ, nếu value là loại datetime thì giờ, phút, giây, tzinfo sẽ bị cắt bớt.

    Return type: str

  9. static today (*args)

    Trả về ngày hiện tại, lúc nửa đêm (00:00:00).

Các trường quan hệ

Trường Many2one

Giá trị của một trường như vậy là một tập bản ghi có kích thước 0 (không có bản ghi) hoặc 1 (một bản ghi duy nhất).

class Student(models.Model)
    _name = 'education.student'

    class_id = fields.Many2one('education.class', string='Class')
Tham số:
  1. comodel_name (str): tên của model đích Mandatory ngoại trừ các trường liên quan hoặc mở rộng.

  2. domain: dùng để lọc dữ liệu theo một điều kiện nào đó (miền hoặc chuỗi).

  3. context (dict): ngữ cảnh tùy chọn để sử dụng ở phía liên kết đến bản ghi khi xử lý trường đó.

  4. ondelete (str): phải làm gì khi bản ghi trong comodel_name bị xóa. Giá trị có thể là:

    • set null: khi bản ghi bị xóa thì thông tin liên kết đến bản ghi sẽ đưa về rỗng.

    • restrict: khi đã có thông tin liên kết đến bản ghi thì không cho phép xóa bản ghi

    • cascade: Khi xóa bản ghi thì xóa những thông tin liên kết đến bản ghi.

  5. auto_join (bool): các lệnh JOINS có được tạo khi tìm kiếm thông qua trường đó hay không (mặc định False)

  6. delegate (bool): đặt nó thành True để làm cho các trường của model đích có thể truy cập được từ model hiện tại (tương ứng với _inherits)

  7. check_company (bool): Đánh dấu trường cần xác minh _check_company(). Thêm miền công ty mặc định tùy thuộc vào thuộc tính trường.

Trường One2many

Giá trị của trường One2many là tập hợp các bản ghi trong comodel_name có trường inverse_name bằng bản ghi hiện tại.

class Student(models.Model)
    _name = 'education.class'

    student_ids = fields.One2many('education.student', 'class_id', string='Students')
Tham số:
  1. comodel_name (str): tên của model đích.

  2. inverse_name (str): tên của trường nghịch đảo Many2one trong comodel_name.

  3. domain: miền tùy chọn để lọc các giá trị của bản ghi ở phía comodel_name (miền hoặc chuỗi).

  4. auto_join (bool): các lệnh JOINS có được tạo khi tìm kiếm thông qua trường đó hay không (mặc định False).

  5. limit (int): giới hạn tùy chọn để sử dụng khi đọc.

Các thuộc tính comodel_nameinverse_name là bắt buộc ngoại trừ trường hợp các trường liên quan hoặc phần mở rộng trường.

Trường Many2many

Giá trị của trường Many2many là tập hợp các bản ghi.

Tham số:
  1. comodel_name (str): tên của model đích, bắt buộc nhập.

  2. relation (str): tên của bảng quan hệ được lưu trữ trong database.

  3. column1 (str): tên của cột đề cập đến bản ghi này trong bảng relation.

  4. column2 (str): tên của cột đề cập đến những bản ghi của comodel_name trong bảng relation.

Các thuộc tính relationcolumn1column2 có thể tự đặt. Nếu không được cung cấp, tên bảng sẽ tự động được tạo model_namecomodel_name!

Lưu ý việc có một số trường với các tham số quan hệ ngầm định trên một model nhất định với cùng comodel_name không được ORM chấp nhận, vì các trường đó sẽ sử dụng cùng một bảng. ORM ngăn hai trường Many2many sử dụng các tham số quan hệ giống nhau, ngoại trừ trường hợp:

  • Cả hai trường sử dụng cùng một model, comodel_name và các tham số quan hệ phải định nghĩa rõ.

  • Ít nhất một trường thuộc model được gắn thuộc tính _auto = False.

Tham số:
  1. domain: miền tùy chọn để lọc các giá trị của bản ghi ở phía comodel_name (miền hoặc chuỗi).

  2. context (str): ngữ cảnh tùy chọn để sử dụng ở phía comodel_name khi xử lý trường đó.

  3. check_company (bool): Đánh dấu trường cần xác minh _check_company(). Thêm miền công ty mặc định tùy thuộc vào thuộc tính trường.

  4. limit (int): giới hạn tùy chọn để sử dụng khi đọc.

Các trường quan hệ giả

Trường quan hệ giả (không có Foreign Key trong database).

Trường Reference

Giá trị trường được lưu trữ dưới dạng string sau mẫu res_model.res_id trong database.

Trường Many2oneReference

Giá trị trường được lưu trữ dưới dạng integer id trong database.

Trái ngược với các trường Reference, model phải được chỉ định trong một trường Char, tên của nó phải được chỉ định trong thuộc tính model_field cho trường hiện tại Many2oneReference.

Tham số: model_field (str): tên của Char được lưu trữ trên model.

Các trường tính toán

Các trường có thể được tính toán (thay vì đọc trực tiếp từ database) bằng cách sử dụng tham số compute. Nó phải gán giá trị đã tính cho trường. Nếu nó tính toán dựa trên các giá trị của trường khác thì phải chỉ định các trường đó bằng cách sử dụng depends().

from odoo import fields, models, api

class Student(models.Model)
    _inherit = 'education.student'

    gpa = fields.Float('string='Grade Point Average', compute='_compute_gpa')

@api.depends('math_score', 'literature_score')
def _compute_gpa(self):
    for r in self:
        r.gpa = (r.math_score + r.literature_score) / 2
  • Các phụ thuộc có thể là các đường dẫn chấm khi sử dụng các trường con:

    @api.depends('subject_ids.score')
    def _compute_gpa(self):
        for r in self:
            r.gpa = sum(line.score for line in r.subject_ids)
    
  • Tìm kiếm một trường được tính toán cũng có thể được kích hoạt bằng cách sử dụng tham số search. Giá trị là một tên phương thức trả về domain tìm kiếm.

    upper_name = field.Char(compute='_compute_upper', search='_search_upper')
    
    def _search_upper(self, operator, value):
        if operator == 'like':
            operator = 'ilike'
        return [('name', operator, value)]
    

    Phương thức tìm kiếm được gọi khi xử lý miền trước khi thực hiện tìm kiếm thực tế trên mô hình. Nó phải trả về một miền tương đương với điều kiện : field operator value

  • Các trường được tính toán mặc định chỉ được đọc. Để cho phép sửa các giá trị trên một trường được tính toán, hãy sử dụng tham số inverse. Đây là tên của một hàm đảo ngược việc tính toán và thiết lập các trường liên quan:

    birthday = fields.Date(string='Date of Birth', compute='_get_birthday', inverse='_set_birthday', store=True)
    
    @api.depends('address_id.dob')
    def _get_birthday(self):
        for r in self:
            birthday = r.birthday
            if not birthday and r.address_id.dob:
                r.birthday = r.address_id.dob
            else:
                r.birthday = birthday
    
    def _set_birthday(self):
        for r in self:
            if r.address_id and r.birthday and r.birthday != r.address_id.dob:
                r.address_id.write({'dob': r.birthday})
    
  • Nhiều trường có thể được tính toán cùng một lúc bằng cùng một phương thức, chỉ cần trên tất cả các trường đặt tên phương thức giống nhau:

    from odoo import fields, models, api
    
    class Class(models.Model)
        _inherit = 'education.class'
    
        no_students_poor = fields.Integer(compute='_compute_num_student')
        no_students_good = fields.Integer(compute='_compute_num_student')
    
        @api.depends('student_ids.type')
        def _compute_num_student(self)
            for r in self:
                r.no_students_poor = len(student.type == 'poor' for student in r.student_ids)
                r.no_students_good = len(student.type == 'good' for student in r.student_ids)
    

    Cảnh báo

    Mặc dù có thể sử dụng cùng một phương pháp tính toán cho nhiều trường, nhưng không nên làm như vậy đối với phương thức nghịch đảo. Trong quá trình tính toán nghịch đảo, tất cả các trường sử dụng nghịch đảo đã nói đều được bảo vệ, có nghĩa là chúng không thể được tính toán, ngay cả khi giá trị của chúng không có trong bộ nhớ cache.

    Nếu bất kỳ trường nào trong số đó được truy cập và giá trị của nó không có trong bộ nhớ cache, ORM sẽ chỉ trả về giá trị mặc định False cho các trường này. Điều này có nghĩa là giá trị của các trường nghịch đảo (không phải là giá trị kích hoạt phương thức nghịch đảo) có thể không cung cấp giá trị chính xác của chúng và điều này có thể sẽ phá vỡ kết quả mong đợi của phương thức nghịch đảo.

Các trường tự động

id

Định danh field

Nếu số phần tử của tập bản ghi hiện tại là 1, trả về id của bản ghi duy nhất đó.

Cảnh báo lỗi nếu không có.

Các trường truy cập nhật ký

Các trường này được tự động đặt và cập nhật nếu _log_access được bật. Nó có thể bị vô hiệu hóa để tránh tạo hoặc cập nhật các trường đó trên các bảng mà chúng không hữu ích.

Mặc định _log_access được đặt thành giá trị tương tự như _auto.

create_date

lưu trữ khi bản ghi đc tạo, kiểu Datetime.

create_uid

lưu trữ người dùng đã tạo bản ghi, Many2one tới res.users.

write_date

lưu trữ thời điểm cập nhật bản ghi lần cuối.

write_uid

lưu trữ người dùng đã cập nhật bản ghi lần cuối, Many2one tới res.users

Cảnh báo

_log_access phải được bật trên TransientModel.

Các trường dành riêng

Một số tên trường được giữ chỗ cho các hành động được xác định ngoài các trường tự động. Chúng phải được xác định trên một model khi hành động liên quan mong muốn:

name

được lấy để đặt giá trị mặc định cho _rec_name, sử dụng để hiển thị tên của bản ghi trong các ngữ cảnh, kiểu Char.

active

chuyển đổi chế độ hiển thị của bản ghi, nếu active được đặt thành False bản ghi là ẩn trong hầu hết các tìm kiếm và danh sách, kiểu Boolean.

state

các giai đoạn của model, được sử dụng trong thuộc tính states của fields, kiểu Selection.

parent_id

giá trị mặc định của _parent_name, được sử dụng để tổ chức các bản ghi trong cấu trúc cây, cho phép sử dụng toán tử child_ofparent_of trong các miền, kiểu Many2one.

parent_path

Khai báo khi parent_store=True, được sử dụng để lưu trữ đường dẫn của cấu trúc cây _parent_name và để tối ưu hóa các toán tử child_ofparent_of trong miền khi tìm kiếm. Trong trường này thuộc tính index=True phải được đặt, kiểu Char.

company_id

Trường chính để sử dụng đa công ty trong Odoo

Được sử dụng :meth:~odoo.models._check_company để kiểm tra tính nhất quán của nhiều công ty. Xác định liệu một bản ghi được chia sẻ giữa các công ty (không có giá trị) hay chỉ những người dùng của một công ty nhất định mới có thể truy cập được. Many2one tới res.company.

Recordsets

Ghi lại bộ nhớ cache và prefetching

Cache: bộ nhớ đệm.

Prefetching: nạp trước một tài nguyên vào bộ nhớ đệm, để giảm thời gian chờ đợi việc truy cập tài nguyên đó khi có yêu cầu.

Odoo duy trì một bộ nhớ cache cho các trường của các bản ghi, vì vậy không phải mọi yêu cầu truy cập trường đều phải truy vấn database, điều mà sẽ gây ảnh hưởng không tốt đến hiệu suất. Ví dụ sau chỉ truy vấn database cho câu lệnh đầu tiên:

student.name                # lần đầu sẽ truy cập database để đọc giá trị trường `name`
student.name                # lần thứ hai sẽ lấy giá trị trong bộ nhớ đệm

Để tránh đọc một trường trên một bản ghi tại một thời điểm, Odoo tìm nạp trước các bản ghi và trường theo một số phương pháp heuristics để có được hiệu suất tốt. Khi một trường phải được đọc trên một bản ghi nhất định, ORM thực chất đọc trường đó trên một tập bản ghi lớn hơn và lưu trữ các giá trị trả về trong bộ nhớ đệm để sử dụng sau. Tập bản ghi được tìm nạp trước thường là tập bản ghi mà từ đó bản ghi được lặp lại. Hơn nữa, tất cả các trường được lưu trữ đơn giản (boolean, integer, float, char, text, date, datetime, selection, many2one) đều được tìm nạp hoàn toàn; chúng tương ứng với các cột trong bảng của model và được tìm nạp một cách hiệu quả trong cùng một truy vấn.

Ví dụ students là một recordset gồm 1000 record. Nếu không tìm nạp trước, vòng lặp sẽ thực hiện 2000 truy vấn đến database. Với tìm nạp trước, chỉ một truy vấn được thực hiện:

students = self.env['education.student'].search([])
for student in students:
    print(student.name)            # lần đầu sẽ tìm nạp các trường 'name' và 'age' và cả các trường khác trên 'students'.
    print(student.age)

Prefetching cũng hoạt động trên các bản ghi thứ cấp: khi các trường quan hệ được đọc, giá trị của chúng (là các bản ghi) được đăng ký để tìm nạp trước trong tương lai. Truy cập vào một trong những bản ghi phụ đó tìm nạp trước tất cả các bản ghi phụ thuộc cùng model. Điều này làm cho ví dụ sau chỉ tạo ra hai truy vấn, một cho các học sinh và một cho các quốc gia:

countries = set()
for student in students:
    country = student.country_id        # lần đầu sẽ tìm nạp tất cả các 'students'
    countries.add(country.name)        # lần đầu sẽ tìm nạp tất cả các 'countries'

Environment

Environment lưu trữ các dữ liệu ngữ cảnh khác nhau được ORM sử dụng: con trỏ database (để truy vấn cơ sở dữ liệu), người dùng hiện tại (để kiểm tra quyền truy cập) và ngữ cảnh hiện tại (lưu trữ metadata tùy ý). Environment cũng lưu trữ bộ nhớ đệm.

Tất cả recordsets đều có một môi trường bất biến, có thể truy cập bằng cách sử dụng env và cấp quyền truy cập:

  • người dùng hiện tại (user)

  • con trỏ (cr)

  • superuser flag (su)

  • hoặc ngữ cảnh (context)

>>> records.env
<Environment object ...>
>>> records.env.user
res.user(3)
>>> records.env.cr
<Cursor object ...)

Khi tạo một recordsets từ một recordsets khác, Environment được kế thừa. Environment có thể được sử dụng để lấy một recordsets trống trong một model khác và truy vấn model đó:

>>> self.env['education.student']
education.student()
>>> self.env['education.student'].search([('sex', '=', 'male')])
education.student(7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74)

Các thuộc tính và phương thức của Environment:

ref (xml_id, raise_if_not_found=True)

Trả về record tương ứng với xml_id đã cho.

lang

Trả về mã ngôn ngữ hiện tại, kiểu str.

user

Trả về người dùng hiện tại.

company

Trả về công ty hiện tại.

nếu không được chỉ định trong ngữ cảnh (allowed_company_ids), trả về công ty chính của người dùng hiện tại.

Raises: AccessError - nội dung khóa ngữ cảnh không hợp lệ hoặc trái phép allowed_company_ids.

Return: công ty hiện tại (mặc định là self.user.company_id).

Return type: res.company

Cảnh báo

Không có giới hạn truy cập nào được áp dụng trong chế độ sudo! Khi ở chế độ sudo, người dùng có thể truy cập vào bất kỳ công ty nào, ngay cả khi ở trong các công ty không được phép của anh ta.

Điều này cho phép kích hoạt các sửa đổi giữa các công ty, ngay cả khi người dùng hiện tại không có quyền truy cập vào công ty được nhắm đến.

companies

Trả về recordset các công ty đã được kích hoạt.

Nếu không được chỉ định trong ngữ cảnh (allowed_company_ids), trả về công ty chính của người dùng hiện tại.

Raises: AccessError - nội dung khóa ngữ cảnh không hợp lệ hoặc trái phép allowed_company_ids.

Return: công ty hiện tại (self.user.company_ids).

Return type: res.company

Cảnh báo

Không có giới hạn truy cập nào được áp dụng trong chế độ sudo! Khi ở chế độ sudo, người dùng có thể truy cập vào bất kỳ công ty nào, ngay cả khi ở trong các công ty không được phép của anh ta.

Điều này cho phép kích hoạt các sửa đổi giữa các công ty, ngay cả khi người dùng hiện tại không có quyền truy cập vào công ty được nhắm đến.

Thay đổi Environment

with_context ([context], [**overrides])

Trả về phiên bản mới của recordset này với ngữ cảnh mở rộng. Ngữ cảnh mở rộng có thể được bổ sung vào ngữ cảnh cũ hoặc ghi đè lên ngữ cảnh cũ.

# current context is {'key1': True}
r2 = records.with_context({}, key2=True)
# -> r2._context is {'key2': True}
r2 = records.with_context(key2=True)
# -> r2._context is {'key1': True, 'key2': True}

with_user (user)

Trả về phiên bản mới của recordset này được đính kèm với người dùng nhất định, ở chế độ không phải superuser, trừ khi usersuperuser (theo quy ước, superuser luôn ở chế độ superuser).

with_company (company)

Trả lại phiên bản mới của recordset này với ngữ cảnh đã sửa đổi, như sau:

result.env.company = company
result.env.companies = self.env.companies | company

Thông số: company (res_company hoặc int) - công ty chính của env mới.

Cảnh báo

Khi sử dụng một công ty trái phép cho người dùng hiện tại, việc truy cập (các) công ty đó trên env có thể kích hoạt AccessError nếu không được thực hiện trong một env không hợp lệ.

with_env (env)

Trả về một phiên bản mới của recordset này được đính kèm với env đã cung cấp.

Thông số: env (Environment)

Cảnh báo

Environment mới sẽ không được hưởng lợi từ cache của database môi trường hiện tại, vì vậy việc truy cập dữ liệu sau này có thể bị chậm trễ hơn trong khi tìm nạp lại từ database. Recordset được trả về có cùng đối tượng tìm nạp trước self.

sudo ([flag=True])

Trả về phiên bản mới của recordset này với chế độ superuser được bật hoặc tắt, tùy thuộc vào flag. Chế độ superuser không thay đổi người dùng hiện tại và chỉ bỏ qua kiểm tra quyền truy cập.

Cảnh báo

Việc sử dụng sudo có thể khiến quyền truy cập dữ liệu vượt qua ranh giới của các quy tắc bản ghi, có thể trộn lẫn các bản ghi có ý nghĩa tách biệt (ví dụ: bản ghi từ các công ty khác nhau trong môi trường đa công ty).

Nó có thể dẫn đến kết quả không trực quan trong các phương pháp chọn một bản ghi trong số nhiều bản ghi - ví dụ như nhận công ty mặc định hoặc chọn một BOM.

Ghi chú

Bởi vì các quy tắc bản ghi và kiểm soát truy cập sẽ phải được đánh giá lại, tập bản ghi mới sẽ không được hưởng lợi từ cache của môi trường hiện tại, do đó, việc truy cập dữ liệu sau này có thể bị chậm trễ hơn trong khi tìm nạp lại từ database. Recordset được trả về có cùng đối tượng tìm nạp trước self.

Thực thi SQL

Thuộc tính cr trên env là con trỏ cho giao dịch cơ sở dữ liệu hiện tại và cho phép thực thi SQL trực tiếp, đối với các truy vấn khó diễn đạt bằng ORM (ví dụ: các phép nối phức tạp) hoặc vì lý do hiệu suất:

self.env.cr.execute("some_sql", params)

Bởi vì các models sử dụng cùng một con trỏ với Environment và chứa các bộ nhớ đệm khác nhau, các bộ nhớ đệm này phải bị vô hiệu khi thay đổi dữ liệu database bằng SQL, nếu không thì việc sử dụng dữ liệu các model có thể trở nên bất đồng nhất. Cần phải xóa bộ nhớ đệm khi sử dụng CREATE hoặc UPDATE hoặc DELETE trong SQL, nhưng không cần thiết khi sử dụng SELECT (vì chỉ đọc vào database).

Ghi chú

Xóa bộ nhớ đệm có thể được thực hiện bằng phương thức invalidate_cache().

invalidate_cache (fnames=None, ids=None)

Vô hiệu hóa bộ nhớ cache của bản ghi sau khi một số bản ghi đã được sửa đổi. Nếu cả fnamesidsNone, toàn bộ bộ nhớ cache sẽ bị xóa.

Tham số

fnames: danh sách các trường đã thay đổi hoặc None cho tất cả các trường. ids: danh sách các id của bản ghi đã thay đổi hoặc None cho tất cả.

Cảnh báo

Việc thực thi SQL trực tiếp sẽ bỏ qua ORM và do đó sẽ bỏ qua quy tắc bảo mật Odoo. Cần đảm bảo rằng các truy vấn của bạn được làm sạch khi sử dụng đầu vào của người dùng và nên sử dụng các tiện ích ORM hơn nếu bạn không thực sự cần sử dụng các truy vấn SQL.

Các phương thức ORM phổ biến

Thông tin recordset

ids

Trả lại danh sách id tương ứng với self.

env

Trả về Environment của bản ghi đã cho.

exists()

Trả về tập hợp các bản ghi hiện có trong self và đánh dấu các bản ghi đã xóa trong bộ nhớ cache. Nó có thể sử dụng để kiểm tra trên các bản ghi.

if record.exists():
    ...

Theo quy ước trả về các bản ghi hiện có.

ensure_one()

Xác nhận recorset hiện tại chỉ có 1 bản ghi.

Raises: odoo.exceptions.ValueError nếu len(self) != 1.

name_get()

Trả về tên hiển thị cho các bản ghi trong self. Theo mặc định đây là giá trị của trường display_name.

Return danh sách các cặp (id, text_repr) cho mỗi bản ghi.

Return type list(tuple)

get_metadata()

Trả lại một số siêu dữ liệu của các bản ghi đã cho.

Return danh sách các dict cho mỗi bản ghi được yêu cầu.

Return type danh sách các dict với các khóa sau:

id: id của đối tượng.

create_uid: người dùng đã tạo bản ghi.

create_date: ngày tạo bản ghi.

write_uid: người dùng cuối cùng đã thay đổi bản ghi.

write_date: ngày thay đổi cuối cùng bản ghi.

xmlid: ID xml được sử dụng để tham chiếu đến bản ghi này (nếu có), ở định dạng module.name.

noupdate: True hoặc False, cho biết liệu bản ghi có được cập nhật hay không.