odoo ORM API學習總結兼orm學習教程

来源:https://www.cnblogs.com/shouke/archive/2023/03/11/17135896.html
-Advertisement-
Play Games

環境 odoo-14.0.post20221212.tar ORM API學習總結/學習教程 模型(Model) Model欄位被定義為model自身的屬性 from odoo import models, fields class AModel(models.Model): _name = 'a. ...


環境

odoo-14.0.post20221212.tar

ORM API學習總結/學習教程

模型(Model)

Model欄位被定義為model自身的屬性

from odoo import models, fields
class AModel(models.Model):
    _name = 'a.model.name'

    field1 = fields.Char()

警告

欄位的名稱和方法的名稱不能相同,最後定義的方法、函數名稱會覆蓋前面定義的相同名稱。

預設的,欄位的標簽(Lable,即用戶可見欄位名稱)為對應欄位名稱開頭字母改成大寫後的值,可通過 string 欄位屬性改成修改欄位Label

field2 = fields.Integer(string="Field Label")

可通過default,定義預設值:

name = fields.Char(default="a value")

預設值也可以通過函數獲取:

    def _default_name(self):
        return 'Title'

name = fields.Char(default=lambda self: self._default_name())

API

BaseModel

class odoo.models.BaseModel[源代碼]

Odoo模型的基類。Odoo mode可通過繼承一下類來創建Model:

  • Model 用於常規資料庫持久化模型
  • TransientModel 用於臨時數據,存儲在資料庫中,但每隔一段時間就會自動清空
  • AbstractModel 用於多繼承模塊共用的抽象父類,不會在資料庫中創建模型表

系統為每個資料庫自動實例化每個模型一次。這些實例表示每個資料庫上的可用模型,取決於該資料庫上安裝的模塊。每個實例的實際類都是從創建和繼承相應模型的Python類構建的。

每個模型實例都是一個“記錄集(recordset)”,即模型記錄的有序集合。記錄集由 browse(), search()或欄位訪問等方法返回。記錄沒有顯式的表示:單條記錄表示為一條記錄的記錄集。

要創建不需要實例化的類,可以將 _register 屬性設置為False

  • _auto= False

    是否應該創建資料庫表。如果設置為 False, 應該重寫 init()來創建資料庫表。預設設。針對ModelTransientModel自動設置為False,針對AbstractModel自動設置為False。可通過繼承AbstractModel來創建不需要任何數據表的模型

  • _log_access

    ORM是否自動生成和更新 Access Log fields。預設_auto的值。

  • _table= None

    模型對應的資料庫表的名稱。如果_auto設置為True的話。

  • _sequence= None

    用於ID欄位的SQL序列

  • _sql_constraints= []

    sql約束,格式:[(name, sql_def, message)]

  • _register= True

    registry visibility

  • _abstract= True

    是否為抽象模型

  • _transient= False

    是否為transient模型

  • _name= None

    模型名稱(以 點分式命名的模塊名稱,比如estate.users

  • _description= None

    模塊描述,非整數名稱

  • _inherit= None

    繼承的Python模型:需要繼承模型的名稱(_name屬性值)或者名稱列表(list類型)

  • _inherits= {}(不太理解)

    dictionary {‘parent_model’: ‘m2o_field’} mapping the _name of the parent business objects to the names of the corresponding foreign key fields to use:

    _inherits = {
        'a.model': 'a_field_id',
        'b.model': 'b_field_id'
    }
    

    implements composition-based inheritance: the new model exposes all the fields of the inherited models but stores none of them: the values themselves remain stored on the linked record.

    警告

    if multiple fields with the same name are defined in the _inherits-ed models, the inherited field will correspond to the last one (in the inherits list order).

  • _rec_name= None

    用於標記記錄的欄位,預設值:name

  • _order= 'id'

    用於搜索結果的預設排序欄位

  • _check_company_auto= False

    執行writecreate, 對擁有 check_company=True屬性的關聯欄位調用_check_company 以確保公司一致性

  • _parent_name= 'parent_id'

    用作父欄位的many2one欄位

  • _parent_store= False

    設置為True以計算parent_path欄位。與parent_path 欄位一起,設置記錄樹結構的索引存儲,以便使用child_ofparent_of域運算符對當前模型的記錄進行更快的分層查詢

  • _date_name= 'date'

    用於預設日曆視圖的欄位

  • _fold_name= 'fold'

    用於確定看板視圖中摺疊組的欄位

AbstractModel

odoo.models.AbstractModel[源代碼]

odoo.models.BaseModel的別名

Model

class odoo.models.Model[源代碼]

常規資料庫持久化Odoo模型的主要父類。

通過繼承此類來創建Odoo模型的:

class user(Model):
    ...

系統將為安裝了該類模塊的每個資料庫實例化一次類

  • _auto= True

    是否應該創建資料庫表。如果設置為 False, 應該重寫 init()來創建資料庫表。預設設。針對ModelTransientModel自動設置為False,針對AbstractModel自動設置為False。可通過繼承AbstractModel來創建不需要任何數據表的模型

  • _abstract= False

    是否為抽象模型

  • _transient= False

    是否為transient模型

TransientModel

class odoo.models.TransientModel[源代碼]

用於臨時記錄的父類模型,旨在暫時保持,並定期進行清理

TransientModel具有簡化的訪問許可權管理,所有用戶都可以創建新記錄,並且只能訪問他們創建的記錄。超級用戶可以無限制地訪問所有TransientModel記錄。

  • _auto= True

    是否應該創建資料庫表。如果設置為 False, 應該重寫 init()來創建資料庫表。預設設。針對ModelTransientModel自動設置為False,針對AbstractModel自動設置為False。可通過繼承AbstractModel來創建不需要任何數據表的模型

  • _abstract= False

    是否為抽象模型

  • _transient= False

    是否為transient模型

欄位(Fields)

class odoo.fields.Field[源代碼]

欄位擁有以下屬性

  • string (str) – 用戶看到的欄位的標簽;如果未設置,ORM將採用類中的欄位名開頭字母改成大寫後的

  • help (str) – 用戶看到的欄位的提示條(設置該屬性後,當滑鼠懸停在欄位標簽上方時,會自動浮現提示條,顯示該屬性的文字內容)。

  • invisible – 欄位是否可見。預設為False,即可見

  • readonly (bool) – 欄位在用戶界面是否只讀,預設值 False,僅對UI起作用

  • required (bool) – 欄位在用戶界面是否必填,預設 False。這通過在資料庫層面為列添加NOT NULL 約束來實現

  • index (bool) – 是否為欄位添加索引。註意:對不存儲、虛擬欄位不起作用。預設值: False

  • default (值或者可調用對象) – 設置欄位的預設值。可以是靜態值,或者以結果集為入參,返回某個值的函數。使用 default=None捨棄該欄位的預設值。

  • states (dict) –將state值映射到UI屬性-值對列表的字典映射,簡單說就是允許用戶界面依據state欄位的值來動態設置對應欄位的UI屬性,因此,它要求存在一個state欄位併在視圖中使用(即使是隱藏的),state屬性的名稱是在odoo硬編碼且不允許修改的,可用屬性有: readonly, required, invisible。例如states={'done':[('readonly',True)]},表示當state值為done時,將用戶界面states所在欄位在設置為只讀(僅針對UI層面)

    用法舉例:

    state = fields.Selection([
            ('draft', 'To Submit'),
            ('cancel', 'Cancelled'),
            ('confirm', 'To Approve'),
            ('refuse', 'Refused'),
            ('validate1', 'Second Approval'),
            ('validate', 'Approved')
            ], string='Status', readonly=True, copy=False, default='confirm')
    date_from = fields.Datetime(
            'Start Date', readonly=True, index=True, copy=False,
            states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
    
  • groups (str) – 值為逗號分隔的組XML ID列表,如groups='base.group_user,base.group_system',可限制欄位只能被給定組用戶訪問。

  • company_dependent (bool) –

    欄位值是否依賴於當前公司,如果設置為True,則表示依賴當前公司,即欄位值和公司綁定。這個屬性的作用就是讓同一欄位,可以根據不同公司,存儲不同的值,假設一個用戶屬於多個公司,他在不同公司的職務也不一樣,此時就可以設置該屬性為True

    該值未存儲在當前模型表中。它註冊為ir.property,也就是說它的值存儲在ir_property表中,通過查詢該表來獲取該欄位的值。

  • copy (bool) – 當記錄重覆時,該欄位值是否被拷貝(在使用 ORM copy()方法複製並生成新記錄時,不複製該欄位的值)。 (針對普通欄位,預設值為: True ,針對one2many和計算欄位,包括屬性欄位(property fields,個人理解註冊ir.property的欄位)和關係欄位,預設值為False

  • store (bool) – 該欄位是否存儲到資料庫,針對計算欄位,預設值為False,其它欄位預設為True

  • group_operator (str) –

    在當前欄位上分組時,供 read_group() 使用的聚合函數

    支持的聚合函數:

    • array_agg : 值,包括空值,連接成一個數組
    • count : 記錄數
    • count_distinct : 不重覆記錄數
    • bool_and : 如果所有值都為真,則為真,否則為假
    • bool_or : 如果至少有一個值為真,則為真,否則為假
    • max : 所有值的最大值
    • min : 所有值的最小值
    • avg :所有值的平均值(算術平均值)
    • sum : 所有值的總和
  • group_expand (str) –

    用於在當前欄位上分組時用於擴展 read_group 結果的函數

    @api.model
    def _read_group_selection_field(self, values, domain, order):
        return ['choice1', 'choice2', ...] # available selection choices.
    
    @api.model
    def _read_group_many2one_field(self, records, domain, order):
        return records + self.search([custom_domain])
    

基礎欄位

class odoo.fields.Boolean[源代碼]

bool的封裝

class odoo.fields.Char[源代碼]

基本字元串欄位,長度有限,通常在客戶端顯示為單行字元串

參數:

  • size(int) – 為該欄位可存儲最大值

  • trim(bool) – 說明該值是否被修剪(預設情況下, True)。請註意,修剪操作僅由 Web 客戶端應用。

  • translate(bool 或者可調用對象)– 啟用欄位值的翻譯;用於translate=True整體翻譯欄位值;translate 也可以是可調用的,從而使得translate(callback,value)通過使用callback(term)來檢索術語的翻譯來翻譯value`

class odoo.fields.Float[源代碼]

float的封裝

精度數字由可選的digitals屬性給出。

參數

  • digits (tuple(int, int), 或者str ) – 一個元組(total, decimal) 或者引用DecimalPrecision 記錄的字元串

    digits=(8,2) 表示總的8位,小數點占2位
    

Float類為此提供了一些靜態方法:

round()以給定精度對浮點值進行舍入。is_zero()檢查浮點值在給定精度下是否等於零。compare()按給定精度比較兩個浮點值。

例子:

fields.Float.round(self.product_uom_qty, precision_rounding=self.product_uom_id.rounding)
fields.Float.is_zero(self.product_uom_qty, precision_rounding=self.product_uom_id.rounding)
field.Float.compare(self.product_uom_qty, self.qty_done, precision_rounding=self.product_uom_id.rounding)

比較助手出於歷史目的使用__cmp_語義,因此使用此助手的正確慣用方式如下:

如果result==0,則第一個和第二個浮點數相等,如果result<0,第一個浮點數小於第二個,如果result>0,第一個浮動點數大於第二個浮動點數

class odoo.fields.Integer[源代碼]

int的封裝

高級欄位

class odoo.fields.Binary[源代碼]

封裝二進位內容(比如一個文件)。

參數:

  • attachment(bool) – 欄位是否存儲為ir_attachment還是該model表的一列(預設為: True`,即存儲為前者。
class odoo.fields.Html[源代碼]

html代碼內容的封裝

參數:略

class odoo.fields.Image[源代碼]

圖片的封裝,擴展Binary

如果圖像大小大於像素的max_width/max_height限制,則通過保持縱橫比將圖像大小調整到該限制。

參數:

  • max_width(int ) – 圖像的最大寬度(預設值:0,無限制)

  • max_height ( int) – 圖像的最大高度(預設值:0,無限制)

  • verify_resolution ( bool) – 是否應驗證圖像解析度以確保它不會超過最大圖像解析度(預設值:True。最大圖像解析度請參閱odoo.tools.image.ImageProcess(預設值:50e6)。

    參數

如果沒有指定 max_width/max_height 或者設置為0,且verify_resolutionFalse,則不會驗證欄位內容,此時應該使用Binary欄位。

class odoo.fields.Monetary[源代碼]

封裝以給定res_currency表示的浮點值。

小數精度和貨幣符號取自currency_field屬性。

參數:

  • currency_field (str) –擁有表示該貨幣欄位的res_currencyMany2one欄位名稱(預設: 'currency_id')
class odoo.fields.Selection[源代碼]

封裝不同值之間的互斥選擇。

說明:Selection欄位的可選值,存儲在public.ir_model_fields_selection表中,通過field_id欄位通過public.ir_model_fields表進行

-- 查詢Selection欄位ID
SELECT id FROM public.ir_model_fields
where model = 'stock.quality' and name='state' 

-- 查詢Selection欄位可選值
select * from public.ir_model_fields_selection where field_id = 13028; -- 13028為Selection欄位ID

參數:

  • selection (list(tuple(str, str)) 或者可調用對象 或者 str)) – 指定欄位的可選值。其值為包含2元組的列表,或者返回前者模型方法,或者方法名稱

  • selection_add (list(tuple(str, str)) –

    在重寫欄位的情況下,提供selection的擴展。它是一個包含二元組(value, label)或者單元組(value,)的列表,其中,單元組中的value必須作為value出現在selection列表中的元組中。新值插入順序和原有selection中元組順序保持一致:

    selection = [('a', 'A'), ('b', 'B')]
    selection_add = [('c', 'C'), ('b',)]
    > result = [('a', 'A'), ('c', 'C'), ('b', 'B')]
    
  • ondelete

    為帶有selection_add的任何重寫欄位提供回退機制。這是一個將selection_add中的每個選項映射到回退操作的dict。

    此回退操作將應用於其selection_add選項映射到該操作的所有記錄。

    這些操作可以是以下任一操作:

    • set null預設情況下,具有此選項的所有記錄的選擇值都將設置為False。
    • cascade–具有此選項的所有記錄將與選項本身一起刪除。
    • set default-具有此選項的所有記錄都將設置為欄位定義的預設值
    • <callable> -一個可調用對象,其第一個也是唯一的參數將是包含指定的Selection選項的記錄集,用於自定義處理

selection屬性選擇是強制性的,除非是related或擴展的欄位

class odoo.fields.Text[源代碼]

類似Char,用於更長的內容,沒有大小,通常展示為多行文本框。

參數:

translate (bool 或者可調用對象) – 同 Char

Date(time) 欄位

當將一個值賦值給 Date/Datetime 欄位時,以下選擇是合法的:

  • datedatetime 對象.
  • 正確格式的字元:
    • Date欄位採用YYYY-MM-DD
    • Datetime欄位採用 YYYY-MM-DD HH:MM:SS
  • False 或者 None.

DateDatetime 欄位類擁有以下輔助函數,用於嘗試轉換為相容類型:

示例

解析來自外部的日期/日期時間:

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

Date/Datetime 比較最佳實踐:

  • Date欄位只能和date對象比較
  • Datetime欄位只能和datetime對象比較

Datetime 欄位在資料庫中存儲為不帶時區的時間戳,並以UTC時區存儲。因為這樣可使Odoo資料庫獨立於托管伺服器系統的時區。時區轉換完全由客戶端管理。

Common operations with dates and datetimes such as addition, subtraction or fetching the start/end of a period are exposed through both Date and Datetime. These helpers are also available by importing odoo.tools.date_utils.

class odoo.fields.Date源代碼

Python date對象的封裝

  • static add(value, *args, **kwargs)

    返回 valuerelativedelta之和

    • 參數

      value – 初始datedatetime

      args – 傳遞給relativedelta的位置參數

      kwargs – 傳遞給relativedelta的關鍵詞參數

    • 返回

      date/datetime結果對象

    示例:

    from odoo.fields import Date
    
    print(Date.add(datetime.now(), years=1)) # 輸出形如:2024-01-03
    # 常見參數:
    # years, months, days, leapdays, weeks, hours, minutes, seconds, microseconds
    
  • static subtract(value, *args, **kwargs)[源代碼]

    返回 valuerelativedelta之差

    • 參數

      value – 初始date 或者datetime

      args – 傳遞給 relativedelta位置參數

      kwargs – 傳遞給 relativedelta的關鍵詞參數

    • 返回

      date/datetime結果對象

  • static context_today(record, timestamp=None)[源代碼]

    按客戶端時區以適合date欄位的格式返回當前日期

    註解

    該方法可能用於計算預設值

    • 參數

      record – 從中獲取時區的記錄集

      timestamp (datetime) – 替代當前日期時間(datetime)的可選的datetime對象

    • 返回類型

      date

  • static end_of(value, granularity)[源代碼]

    從日期或日期時間獲取時間段的結束

    • 參數

      value – 初始datedatetime

      granularity – 字元串表示的時間段類型, 可以是year, quarter, month, week, day 或者hour

    • 返回

      與指定時段的起始對應的date/datetime對象

    示例:

    print(datetime.now()) # 2023-01-03 10:12:32.332208
    print(Date.end_of(datetime.now(), 'year')) # 輸出形如:2023-12-31 23:59:59.999999
    print(Date.end_of(datetime.now(), 'month')) # 輸出形如:2023-01-31 23:59:59.999999
    
  • static start_of(value, granularity)[源代碼]

    從日期或日期時間獲取時間段的開始

    • 參數

      value – 初始datedatetime

      granularity – 字元串表示的時間段類型, 可以是year, quarter, month, week, day 或者hour

    • 返回

      與指定時段的起始對應的date/datetime對象

    示例:

    print(datetime.now()) # 2023-01-03 10:18:57.071276
    print(Date.start_of(datetime.now(), 'year')) # 輸出形如:2023-01-01 00:00:00
    print(Date.start_of(datetime.now(), 'month')) # 輸出形如:2023-01-01 00:00:00
    print(Date.start_of(datetime.now(), 'hour')) # 輸出形如:2023-01-03 10:00:00
    
  • static to_date(value)[源代碼]

    嘗試轉換 valuedate 對象

    警告

    如果value為datetime對象,它將被轉換為date對象,且所有日期時間特定信息(HMS, TZ, …)都會丟失。

    • 參數

      value (str 或 date 或 datetime) –需要轉換的值

    • 返回

      代表 value的對象

    • 返回類型

      date類型或者None

  • static to_string(value)[源代碼]

    date 或者datetime 對象轉為字元串

    • 參數

      value – 需要轉換的日期或者日期時間對象

    • 返回

      以伺服器日期格式返回代表 value 的字元串。如果 valuedatetime類型,自動捨棄小時,分,秒,時區信息。

    • 返回類型:str

    示例:

    print(Date.to_string(datetime.now())) # 輸出形如:2023-01-03
    
  • static today(*args)[源代碼]

    返回當前日期

    示例:

    print(Date.today()) # 格式形如:2023-01-03
    
class odoo.fields.Datetime[源代碼]

Python datetime對象的封裝

  • static context_timestamp(record, timestamp)[源代碼]

    返迴轉換為客戶端時區的給定時間戳。

    註解

    此方法不是用作預設初始值設定項,因為datetime欄位在客戶端顯示時會自動轉換。對於預設值,應使用now()

    • 參數

      record – 從中獲取時區的記錄集。

      timestamp (datetime) – 待轉換為客戶端時區的naive datetime值 (UTC表示的)

    • 返回

      按上下文時區轉換為時區敏感的datetime

    • 返回類型

      datetime

  • static add(value, *args, **kwargs)[源代碼]

    參考Date.add

  • static subtract(value, *args, **kwargs)[源代碼]

    參考Date.subtract

  • static end_of(value, granularity)[源代碼]

    參考Date.end_of

  • static start_of(value, granularity)[源代碼]

    參考Date.start_of

  • static to_string(value)[源代碼]

    參考Date.to_string

  • static today(args)[源代碼]

    返回當天,午夜 (00:00:00)

    示例:

    from odoo.fields import Datetime
    
    print(Datetime.today()) # 輸出形如:2023-01-03 00:00:00
    print(Datetime.now()) # 輸出當前時間 2023-01-03 12:33:00
    
  • static to_datetime(value)[源代碼]

    將ORM value 轉為 datetime

    • 參數

      value (str 或者 date 或者 datetime) – 需要轉換的值

    • 返回

      代表 value的對象

    • 返回類型

      datetime 或者None

關係欄位(Relational Fields)

class odoo.fields.Many2one[源代碼]

Many2one欄位的值是大小為0(無記錄)或1(單個記錄)的記錄集。

參數:

  • comodel_name (str) – 目標模型的名稱,comodel_name是必選參數,除非是相關或擴展欄位(不太理解,原文:name of the target model Mandatory except for related or extended fields)
  • domain – 用於設置客戶端側候選值的可選 domain (domain 或者字元串)
  • context (dict) – 處理該欄位時供客戶端使用的上下文
  • ondelete (str) – 當引用的記錄被刪除時,怎麼處理:可選值有:'set null', 'restrict', 'cascade'
  • auto_join (bool) – 是否在搜索該欄位時生成JOIN (預設: False)
  • delegate (bool) – 將其設置為True以標記可通過當前模型訪問目標模型的欄位(對應_inherits)
  • check_company (bool) – 標記需要在 _check_company()中校驗的欄位。取決於欄位屬性,添加一個預設的公司domain
class odoo.fields.One2many[源代碼]

One2many欄位的值為 comodel_name中所有滿足條件的記錄的結果集,而目標模型中的 inverse_name 則等價於當前記錄。

參數:

  • comodel_name (str) – 目標模型的名稱
  • inverse_name (str) – 目標模型中反向Many2one欄位名稱,根據該欄位反向查詢記錄
  • domain – 用於設置客戶端候選值的條件 (domain 或者字元串),可選
  • context (dict) – 處理該欄位時供客戶端使用的上下文
  • auto_join (bool) – 是否在搜索該欄位時生成JOIN (預設: False)
  • limit (int) – 讀取時用的可選限制

comodel_nameinverse_name 參數是必選參數,除非是相關或者擴展欄位

class odoo.fields.Many2many[源代碼]

Many2many欄位的值為一個結果集。

參數:

  • comodel_name – 目標模型的名稱,必選參數,除非是關聯或者擴展欄位
  • relation (str) – 資料庫中存儲關係的表名,可選參數。
  • column1 (str) – relation表中引用"這些"記錄的列名,可選參數
  • column2 (str) – relation表中引用"那些"記錄的列名,可選參數

relation, column1column2 參數可選。 如果未給定,自動根據模型名稱生成,提供的不同的model_namecomodel_name

註意,ORM不支持在給定模型,使用同樣的comodel,創建多個省略了relation參數的欄位,因為這些欄位將使用相同的表。ORM阻止兩個Many2many欄位使用相同的relation參數,除非:

  • 兩個欄位都使用相同的模型, comodel並顯示指定relation參數,否則
  • 至少有一個欄位屬於攜帶_auto = False的模型

參數:

  • domain – 用於設置客戶端候選值的條件 (domain 或者字元串),可選
  • context (dict) – 處理該欄位時供客戶端使用的上下文
  • check_company (bool) – 標記需要在 _check_company()中校驗的欄位。取決於欄位屬性,添加一個預設的公司條件
  • limit (int) – 讀取時用的可選限制

註意:odoo不會在當前模型對應表中為One2manyMany2many類型的屬性建立對應的表欄位,但會為Many2one類型的屬性建立對應表欄位,針對Many2many類型的屬性,odoo會建立一張輔助表,表名預設格式為model1_table_name_model2_table_name_rel,該表擁有兩列,一列為當前模型表主鍵ID(model1_table_name_id),一列為關係欄位關聯模型表的主鍵ID(model2_table_name_id),這樣通過兩表記錄ID就可以查詢所需記錄了

偽關係欄位

  • class odoo.fields.Reference[源代碼]

    偽關係欄位(資料庫中沒有FK)。該欄位值存儲為資料庫中遵循模式"res_model,res_id"的字元串。

  • class odoo.fields.Many2oneReference[源代碼]

    該欄位的值存儲為資料庫中的一個整數。與odoo.fields.Reference欄位相反,必須在Char類型欄位中指定模型,其中,該欄位的名稱必須在當前Many2oneReference欄位中的model_field屬性中指定

    參數:model_field (str) – 存儲模型的欄位名稱。

計算欄位

可以使用 compute 參數計算欄位(而不是直接從資料庫中讀取)它必須將計算值分配給欄位。如果它使用其他欄位的值,則應使用depends()指定這些欄位

from odoo import api
total = fields.Float(compute='_compute_total')

@api.depends('value', 'tax')
def _compute_total(self):
    for record in self:
        record.total = record.value + record.value * record.tax
  • 當使用子欄位時,依賴可使用分點路徑:

    @api.depends('line_ids.value')
    def _compute_total(self):
        for record in self:
            record.total = sum(line.value for line in record.line_ids)
    
  • 預設情況下,不存才計算欄位。他們在請求時被計算並返回。 設置store=True 將在資料庫中存儲計算及欄位並啟動開啟欄位搜索。

  • 也可以通過設置search參數開啟在計算欄位上的搜索。該參數值為一個返回搜索條件的方法名稱 。

    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)]
    

    在對模型進行實際搜索之前處理domain時調用該搜索方法。它必須返回與條件field operator value等效的domain

  • 計算欄位預設值。為了允許對計算欄位進行設置,使用inverse參數。該參數值為反向計算並設置相關欄位的函數的名稱:

    document = fields.Char(compute='_get_document', inverse='_set_document')
    
    def _get_document(self):
        for record in self:
            with open(record.get_document_path) as f:
                record.document = f.read()
    def _set_document(self):
        for record in self:
            if not record.document: continue
            with open(record.get_document_path()) as f:
                f.write(record.document)
    
  • 可以用同一方法同時計算多個欄位,只需對所有欄位使用同一方法並設置所有欄位

    discount_value = fields.Float(compute='_apply_discount')
    total = fields.Float(compute='_apply_discount')
    
    @api.depends('value', 'discount')
    def _apply_discount(self):
        for record in self:
            # compute actual discount from discount percentage
            discount = record.value * record.discount
            record.discount_value = discount
            record.total = record.value - discount
    

警告

雖然可以對多個欄位使用相同的計算方法,但不建議對reverse方法使用相同的方法。

reverse的計算過程中,所有使用所述inverse的欄位都受到保護,這意味著即使它們的值不在緩存中,也無法計算它們。

如果訪問了這些欄位中的任何一個欄位,且並且其值不在緩存中,ORM將簡單的為這些欄位返回預設值False。這意味著這些inverse欄位的值(觸發inverse方法的值除外)可能不會給出正確的值,這可能會破壞inverse方法的預期行為

相關欄位(Related fields)

計算欄位的一種特殊情況是相關(代理)欄位,它提供當前記錄上子欄位的值。它們是通過設置related參數來定義的,與常規計算欄位一樣,它們可以存儲:

nickname = fields.Char(related='user_id.partner_id.name', store=True)

related欄位的值是通過遍歷一系列關係欄位並讀取所訪問模型上的欄位來給出的。要遍歷的欄位的完整序列由related屬性指定

如果未重新定義某些欄位屬性,則會自動從源欄位中複製這些屬性:stringhelprequired(僅當序列中的所有欄位都是必需的時)、groupsdigitssizetranslatecleaning”、“selectioncomodel_namedomaincontext。所有無語義屬性都從源欄位複製。

預設的, related欄位:

  • 不被存儲
  • 不被覆制
  • 只讀
  • 超級用戶模式下被計算

像計算欄位那樣,添加 store=True 以存儲related欄位。當其依賴被修改時,會自動重新計算related欄位。

小技巧

如果不希望在任何依賴項更改時重新計算related欄位,則可以指定精確的欄位依賴項:

nickname = fields.Char(
    related='partner_id.name', store=True,
    depends=['partner_id'])
# nickname僅在partner_id被修改時才會被重新計算,而不會在partner名稱被修改時重新計算

警告

不可以在related欄位依賴項中包含 Many2many 或者 One2many 欄位

related 可以用於引用另一個模型中的 One2manyMany2many 欄位,前提是通過當前模型的一個Many2one關係來實現的。 One2manyMany2many 不被支持,無法正確的彙總結果:

m2o_id = fields.Many2one()
m2m_ids = fields.Many2many()
o2m_ids = fields.One2many()

# Supported
d_ids = fields.Many2many(related="m2o_id.m2m_ids")
e_ids = fields.One2many(related="m2o_id.o2m_ids")

# Won't work: use a custom Many2many computed field instead
f_ids = fields.Many2many(related="m2m_ids.m2m_ids")
g_ids = fields.One2many(related="o2m_ids.o2m_ids")

自動生成的欄位

  • odoo.fields.id

    ID欄位

    如果當前記錄集長度為1,返回記錄集中唯一記錄的ID。否則拋出一個錯誤

訪問日誌欄位

如果啟用_log_access,自動設置並更新這些欄位。當未用到這些欄位時,以禁用它以阻止創建或更新表中這些欄位。

預設的 _log_access被設置為 _auto的值。

  • odoo.fields.create_date

    創建記錄時存儲創建時間,Datetime類型

  • odoo.fields.create_uid

    存儲記錄創建人, Many2one to a res.users

  • odoo.fields.write_date

    存儲記錄最後更新時間,Datetime類型

  • odoo.fields.write_uid

    存儲記錄最後更新人, Many2one to a res.users.

警告

必須對odoo.models.TransientModel模型開啟_log_access

保留欄位名稱

除了自動欄位之外,還有一些欄位名是為預定義行為保留的。當需要相關行為時,應在模型上定義它們:

  • odoo.fields.name

    _rec_name的預設值,用於在需要代表性“命名”的上下文中顯示記錄。odoo.fields.Char類型

  • odoo.fields.active

    切換記錄的全局可見性,如果active設置為False,則記錄在大多數搜索和列表中不可見。odoo.fields.Boolean類型

  • odoo.fields.state

    對象的聲明周期階段,供fields.[Selectionstates 屬性使用

  • odoo.fields.parent_id

    _parent_name的預設值,用於以樹結構組織記錄,併在domain中啟用child_ofparent_of運算符。Many2one欄位。

  • odoo.fields.parent_path

    _parent_store設置為True時,用於存儲反映[_parent_name]樹結構的值,並優化搜索domain中的child_ofparent_of運算符。必須使用index=True聲明才能正確操作。odoo.fields.Char類型

  • odoo.fields.company_id

    用於Odoo多公司行為的主欄位名。供:meth:~Odoo.models._check_company用於檢查多公司一致性。定義記錄是否在公司之間共用(沒有值)還是僅由給定公司的用戶訪問。Many2one:類型:res_company

記錄集(Recordset)

與模型和記錄的交互是通過記錄集執行的,記錄集是同一模型的記錄的有序集合。

警告

與名稱所暗示的相反,記錄集當前可能包含重覆項。這在未來可能會改變。

在模型上定義的方法是在記錄集上執行的,方法的self是一個記錄集:

class AModel(models.Model):
    _name = 'a.model'
    def a_method(self):
        # self can be anything between 0 records and all records in the
        # database
        self.do_operation()

對記錄集進行迭代將產生新的單條記錄的記錄集,這與對Python字元串進行迭代產生單個字元的字元串非常相似:

def do_operation(self):
    print(self) # => a.model(1, 2, 3, 4, 5)
    for record in self:
        print(record) # => a.model(1), then a.model(2), then a.model(3), ...

欄位訪問

記錄集提供了一個“Active Record” 介面:模型欄位可直接作為記錄的屬性直接讀取和寫入。

註解

當訪問潛在多條記錄的記錄集上的非關係欄位時,使用mapped(),該函數返回一個列表:

total_qty = sum(self.mapped('qty')) # mapped返回一個列表,形如[2,4,5]

欄位值也可以像字典項一樣訪問。設置欄位的值會觸發對資料庫的更新:

>>> record.name
Example Name
>>> record.company_id.name
Company Name
>>> record.name = "Bob"
>>> field = "name"
>>> record[field]
Bob

警告

  • 嘗試讀取多條記錄上的欄位將引發非關係欄位的錯誤。
  • 訪問一個關係欄位(Many2oneOne2manyMany2many),總是返回記錄集,如果未設置欄位的話,則返回空記錄集。

記錄緩存和預取

Odoo為記錄的欄位維護一個緩存,這樣,不是每個欄位的訪問都會發出資料庫請求。

以下示例僅為第一條語句查詢資料庫:

record.name             # 第一次訪問從資料庫獲取值
record.name             # 第二次訪問從緩存獲取值

為了避免一次讀取一條記錄上的一個欄位,Odoo會按照一些啟髮式方法預取個記錄和欄位,以獲得良好的性能。一旦必須在給定記錄上讀取欄位,ORM實際上會在更大的記錄集上讀取該欄位,並將返回的值存儲在緩存中以供後續使用。預取的記錄集通常是通過迭代獲得記錄的記錄集。此外,所有簡單的存儲欄位(布爾值、整數、浮點值、字元、文本、日期、日期時間、選擇、many2one)都會被提取;它們對應於模型表的列,併在同一查詢中高效地獲取。

考慮以下示例,其中partners為包含1000條記錄的記錄集。如果不進行預取,迴圈將對資料庫進行2000次查詢。使用預取,只進行一次查詢

for partner in partners:
    print partner.name          # first pass prefetches 'name' and 'lang'
                                # (and other fields) on all 'partners'
    print partner.lang

預取也適用於輔助記錄:當讀取關係欄位時,它們的值(即記錄)將被訂閱以供將來預取。訪問這些輔助記錄之一將預取同一模型中的所有輔助記錄。這使得以下示例僅生成兩個查詢,一個用於合作伙伴,另一個用於國家/地區:

countries = set()
for partner in partners:
    country = partner.country_id        # first pass prefetches all partners
    countries.add(country.name)         # first pass prefetches all countries

方法修飾器

Odoo API模塊定義了Odoo環境和方法修飾符

  • odoo.api.autovacuum(method)[源代碼]

    修飾一個方法,使其由日常vacuum cron作業(模型ir.autovacuum)調用。這通常用於垃圾收集之類的不需要特定cron作業的任務

  • odoo.api.constrains(*args)[源代碼]

    裝飾一個約束檢查器

    每個參數必須是校驗使用的欄位名稱:

    @api.constrains('name', 'description')
    def _check_description(self):
        for record in self:
            if record.name == record.description:
                raise ValidationError("Fields name and description must be different")
    

    當記錄的某個命名欄位被修改時調用裝飾器函數。

    如果校驗失敗,應該拋出 ValidationError

    警告

    @constrains 僅支持簡單的欄位名稱,不支持並忽略點分名稱(關係欄位的欄位,比如 partner_id.customer)

    @constrains 僅當修飾方法中聲明的欄位包含在createwrite調用中時才會觸發。這意味著視圖中不存在的欄位在創建記錄期間不會觸發調用。必須重寫create,以確保始終觸發約束(例如,測試是否缺少值)

  • odoo.api.depends(*args)[源代碼]

    返回一個裝飾器,該裝飾器指定compute方法的欄位依賴關係(對於新型函數欄位)。參數支持是由點分隔的欄位名序列組成的字元串:

    pname = fields.Char(compute='_compute_pname')
    
    @api.depends('partner_id.name', 'partner_id.is_company')
    def _compute_pname(self):
        for record in self:
            if record.partner_id.is_company:
                record.pname = (record.partner_id.name or "").upper()
            else:
                record.pname = record.partner_id.name
    

    有的也可能傳遞一個函數作為參數,這種情況下,依賴通過調用 在這種情況下,通過使用欄位的模型調用函數來提供依賴項

  • odoo.api.depends_context(*args)[源代碼]

    返回一個修飾符,該修飾符指定非存儲的“compute”方法的上下文依賴項。每個參數都是上下文字典中的鍵:

    price = fields.Float(compute='_compute_product_price')
    
    @api.depends_context('pricelist')
    def _compute_product_price(self):
        for product in self:
            if product.env.context.get('pricelist'):
                pricelist = self.env['product.pricelist'].browse(product.env.context['pricelist'])
            else:
                pricelist = self.env['product.pricelist'].get_default_pricelist()
            product.price = pricelist.get_products_price(product).get(product.id, 0.0)
    

    所有依賴項都必須是可哈希的。以下鍵具有特殊支持:

    • company (上下文中的值或當前公司id),
    • uid (當前用戶ID和超級用戶標記),
    • active_test (env.context或者field.context中的值).
  • odoo.api.model(method)[源代碼]

    修飾一個record-style的方法,其中self是一個空記錄集,但其內容不相關,只有模型相關,可以理解為不會創建對應資料庫記錄的模型對象。模型層面的操作需要添加此修飾器,相當於類靜態函數

    @api.model
    def method(self, args):
        ...
    
  • odoo.api.model_create_multi(method)[源代碼]

    修飾一個以字典列表為參數,並創建多條記錄的方法。可能僅通過一個字典或者字典列表調用該方法:

    record = model.create(vals)
    records = model.create([vals, ...])
    
  • odoo.api.onchange(*args)[源代碼]

    返回一個修飾器來修飾給定欄位的onchange方法。

    在出現欄位的表單視圖中,當修改某個給定欄位時,將調用該方法。在包含表單中存在的值的偽記錄上調用該方法。該記錄上的欄位賦值將自動返回客戶端。

    每個參數必須是欄位名:

    @api.onchange('partner_id')
    def _onchange_partner(self):
        self.message = "Dear %s" % (self.partner_id.name or "")
        return {
            'warning': {'title': "Warning", 'message': "What is this?", 'type': 'notification'},
        }
    

    如果類型設置為通知(notification),則警告將顯示在通知中。否則,它將作為預設值顯示在對話框中

    警告

    @onchange 僅支持簡單的欄位名稱,不支持並自動忽略點分名稱(關係欄位的欄位,比如partner_id.tz)

    危險

    由於 @onchange 返回偽記錄的記錄集,對上述記錄集調用任何一個CRUD方法(create(), read(), write(), unlink())都是未定義的行為,因為它們可能還不存在於資料庫中。相反,只需像上面的示例中所示那樣設置記錄的欄位或調用update()方法

    警告

    one2many 或者many2many欄位不可能通過onchange修改其自身。這是客戶端限制 - 查看 #2693

  • odoo.api.returns(model, downgrade=None, upgrade=None)[源代碼]

    為返回model實例的方法返回一個修飾器

    • 參數

      model – 模型名稱,或者表示當前模型的'self'

      downgrade – 一個用於轉換record-style的value為傳統風格輸出的函數downgrade(self, value, *args, **kwargs)

      upgrade – 一個用於轉換傳統風格(traditional-style)的value為record-style的輸出的函數upgrade(self, value, *args, **kwargs)

    參數 self, *args**kwargs以record-style方式傳遞給方法

    修飾器將方法輸出適配api風格: id, ids 或者False 對應傳統風格,而記錄集對應記錄風格:

    @model
    @returns('res.partner')
    def find_partner(self, arg):
        ...     # return some record
    
    # output depends on call style: traditional vs record style
    partner_id = model.find_partner(cr, uid, arg, context=context)
    
    # recs = model.browse(cr, uid, ids, context)
    partner_record = recs.find_partner(arg)
    

    註意,被修飾的方法必須滿足那約定。

    這些修飾器是自動繼承的:重寫被修飾的現有方法的方法將被相同的@return(model)修飾

環境(Environment)

Environment 存儲ORM使用的各種上下文數據:資料庫游標(用於資料庫查詢)、當前用戶(用於訪問許可權檢查)和當前上下文(

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、基本語法元素 1.空白和註釋及語句 (1)空白: 換行符、回車符、空格鍵、水平定位鍵(Tab) 編譯器會忽略掉多餘的空白 作用:增加程式的易讀性 (2)註釋:主要作用是將代碼解釋其功能和作用,在編譯時,編譯器會直接將其丟棄,不會進入執行階段 1)// 在一行內的註釋,此種註釋是同一行內的註釋如果 ...
  • #####需求: 定義一個數組其中包含多個數字。用自己的方式最終實現,奇數放在數組的左邊,偶數放在數組的右邊。(可以創建其他數組,不必須在原數組中改變) 分析: 1.初始化一個數組,裡面既可以存儲奇數也可以存儲偶數(下麵稱這個個數組為原數組)。 2.再次定義兩個數組,一個用來存放從原數組中挑出來的奇 ...
  • VL59 根據RTL圖編寫Verilog程式 這題比較簡單,照著寫就好了。 `timescale 1ns/1ns module RTL( input clk, input rst_n, input data_in, output reg data_out ); reg data_in_reg; al ...
  • 原文鏈接:為什麼 Go 語言 struct 要使用 tags 在 Go 語言中,struct 是一種常見的數據類型,它可以用來表示覆雜的數據結構。在 struct 中,我們可以定義多個欄位,每個欄位可以有不同的類型和名稱。 除了這些基本信息之外,Go 還提供了 struct tags,它可以用來指定 ...
  • 1.全局設置用戶名和郵箱 因為平時除了開發公司項目還會寫自己的項目或者去維護開源項目,一般情況下,公司會要求提交代碼時使用自己的真名或者拼音和公司郵箱,以前就只會設置全局用戶名或郵箱如下 git config --global user.name "username" git config --gl ...
  • 變數和數據類型 所有定義的變數都存在記憶體中,定義變數需要記憶體空間,不同類型的變數需要的記憶體空間是不同的 數據類型作用:告訴編譯器,我這個數據在記憶體中需要多大的空間,編譯器預算對象(變數)分配的記憶體空間大小。 1.常量與變數 1.1 常量 常量:程式運行中不能改變的量 整型常量:1 200 字元常量: ...
  • VS調試以及Qt基本使用 1.彙編語言 1.1 VS中C語言嵌套彙編代碼(瞭解) #include <stdio.h> int main() { //定義整型變數a, b, c int a; int b; int c; __asm { mov a, 3 //3的值放在a對應記憶體的位置 mov b, ...
  • 深夜檔分享,給大家介紹一個黑白的、“驚悚”的網站! 從名字來看(killed by microsoft),是不是猜到點端倪了? 這個神奇的網站居然收錄了微軟壽終正寢的那些軟體。這是一個免費的開放源碼列表,其中列出了已停產的微軟服務、產品、設備和應用程式。網站的目標是成為有關微軟已死項目歷史的真實信息 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...