ORM API
新版本8:這章記錄了Odoo 8.0中添加的新API,它應該是未來的主要開發API。它還提供了關於從版本7和更早版本的“舊API”移植或橋接的信息,但是沒有顯式地記錄那個API。請參閱舊文檔。
模型和記錄的交互是通過記錄集執行的,記錄集是同一模型的一組排序記錄。
注意
與名稱所暗示的相反,目前記錄集可以包含重復的內容。這種情況在未來可能會發生變化。
模型上定義的方法在記錄集中執行,而它們的self
是一個記錄集:
class AModel(models.Model):
_name = 'a.model'
def a_method(self):
# self can be anywhere between 0 records and all records in the
# database
self.do_operation()
print self
可以得到account.asset.asset(5,)
可以看出打印出了操作的記錄
迭代一個記錄集將產生一個單一記錄(“單例”)的新集合,就像在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”接口:模型字段可以作為屬性直接從記錄中讀取和寫入,但僅在單例(單記錄記錄集)上。字段值也可以字典集被訪問,比如,對於動態字段名來說,它比getattr()
更優雅、更安全。設置字段的值會觸發數據庫的更新:
>>> record.name
Example Name
>>> record.company_id.name
Company Name
>>> record.name = "Bob"
>>> field = "name"
>>> record[field]
Bob
嘗試在多個記錄上讀取或寫入字段會引起錯誤。
訪問一個關聯字段(Many2one
, One2many
, Many2many
) 總是返回一個記錄集,如果字段沒有設置,則清空。
注意
每一次指定到一個字段都會觸發一個數據庫更新,當在同一時間設置多個字段或在多個記錄(到相同的值)上設置字段時,使用write()
:
# 3 * len(records) database updates
for record in records:
record.a = 1
record.b = 2
record.c = 3
# len(records) database updates
for record in records:
record.write({'a': 1, 'b': 2, 'c': 3})
# 1 database update
records.write({'a': 1, 'b': 2, 'c': 3})
記錄緩存和預取(Record cache and prefetching)
Odoo為記錄的字段保留了一個緩存,因此不是每個字段訪問都會發出數據庫請求,這對性能來說是很糟糕的。下面的例子只針對第一個語句查詢數據庫:
record.name # first access reads value from database
record.name # second access gets value from cache
為了避免一次在一個記錄上讀取一個字段,Odoo會根據一些試探法預先獲取記錄和字段,以獲得良好的性能。一旦一個字段必須在給定的記錄上讀取,ORM實際上會在較大的記錄集中讀取該字段,並將歸還的值儲存在緩存中以供以后使用。預取的記錄集通常是由迭代產生的記錄集。而且,所有簡單的存儲字段 (boolean, integer, float, char, text, date, datetime, selection, many2one)都是可以完全獲取的;它們對應於model表的列,並在同一個查詢中有效地獲取。
考慮下面的例子,其中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
預取也適用於二級記錄(secondary records):當讀取關系字段時,它們的值(即記錄)將被訂閱以備將來預取。訪問這些二次記錄中的一個,可以從相同的模型中獲取所有的二級記錄。這使得下面的示例只生成兩個查詢,一個用於partners ,一個用於countries:
countries = set()
for partner in partners:
country = partner.country_id # first pass prefetches all partners
countries.add(country.name) # first pass prefetches all countries
集合操作(Set operations)
記錄集是不可變的,但是相同的模型集可以使用不同的set操作來組合,返回新的記錄集。設置操作不保存順序。
record in set
返回中是否record
(必須是一個 1-元素記錄集)在集合中出現。記錄不在集合中是逆操作set1<=set2
和set1<set2
返回set1
是否是set2
的子集(resp,嚴格的)set1 >= set2
和set1 > set2
返回是否set1
是set2
的超集(resp,嚴格的)set1 | set2
返回兩個記錄集的並集,這是一個新的記錄集,其中包含了兩個來源的所有記錄set1 & set2
返回兩個記錄集的交集,一個新的記錄集,其中只包含兩個來源的記錄。set1 - set2
返回一個新的紀錄集,其中只包含set1
的記錄,它不在set2
中
其他記錄集操作
記錄集是可迭代的,所以通常的Python工具可以用於轉換(map()
, sorted()
, itertools.ifilter
, …)。然而,這些返回要么是一個列表
,要么是一個迭代器
,刪除了在結果上調用方法的能力,或者使用set操作。
filtered()
返回一個記錄集,其中只包含滿足所提供的斷言功能的記錄。斷言也可以是一個字符串,由字段為真或假來過濾:
通過條件過濾產生一個記錄集
# only keep records whose company is the current user's
records.filtered(lambda r: r.company_id == user.company_id)
# only keep records whose partner is a company
records.filtered("partner_id.is_company")
sorted()
返回按所提供的key函數排序的記錄集。如果沒有提供key,請使用該模型的默認排序順序:
# sort records by name
records.sorted(key=lambda r: r.name)
mapped()
將所提供的函數應用到記錄集中的每個記錄,如果結果是記錄集,則返回一個記錄集:
# returns a list of summing two fields for each record in the set
records.mapped(lambda r: r.field1 + r.field2)
所提供的函數可以是一個字符串去獲取對應的字段值:
# returns a list of names
records.mapped('name')
# returns a recordset of partners
record.mapped('partner_id')
# returns the union of all partner banks, with duplicates removed
record.mapped('partner_id.bank_ids')
環境(Environment)
Environment是odoo中操作db的總句柄
Environment
存儲ORM所使用的各種上下文數據:數據庫游標(cursor)(用於數據庫查詢)、當前用戶(current user)(用於訪問權限檢查)和當前上下文(儲存任意元數據)。環境也存儲緩存。
引入了環境的概念,它的主要目標是提供對游標、用戶、模型、上下文、記錄集、和緩存的封裝。
所有記錄集都有一個不可變的環境,可以使用env
訪問,並允許訪問當前用戶(user
)、光標(cr
)或上下文(context):
>>> records.env
<Environment object ...>
>>> records.env.user
res.user(3)
>>> records.env.cr
<Cursor object ...)
實際測試打印:
print self.env
<odoo.api.Environment object at 0x7fc51e797f90>
print self.env.cr
<odoo.sql_db.Cursor object at 0x7fc51e71a410>
當從另一個記錄集創建一個記錄集時,環境是繼承的。環境可用於在另一個模型中獲得空記錄集,並查詢該模型:
>>> self.env['res.partner']
res.partner
>>> self.env['res.partner'].search([['is_company', '=', True], ['customer', '=', True]])
res.partner(7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74)
改變環境
可以根據記錄集對環境進行定制。這將使用修改后的環境返回記錄集的新版本。
sudo()
使用提供的用戶集創建一個新環境,如果沒有用戶提供,則創建一個管理員環境(在安全的上下文中繞過訪問權限/規則),新環境被調用時,返回記錄集的副本:
# create partner object as administrator
env['res.partner'].sudo().create({'name': "A Partner"})
# list partners visible by the "public" user
public = env.ref('base.public_user')
env['res.partner'].sudo(public).search([])
實際測試
print self.env['account.asset.asset'].sudo().search([])
account.asset.asset(1, 2, 3, 4, 5)
public = self.env.ref('base.public_user')
print self.env['res.partner'].sudo(public).search([])
# res.partner() 感覺是env是切換表,sudo是拿指定的環境進行關聯查詢
print self.env.user
# res.users(1,)
with_context()
-
可以采用單個位置參數,取代當前環境的上下文
-
可以通過關鍵字獲取任意數量的參數,這些參數被添加到當前環境的上下文或步驟1中設置的上下文環境中。
# look for partner, or create one with specified timezone if none is
# found
env['res.partner'].with_context(tz=a_tz).find_or_create(email_address)
with_env()
完全取代現有的環境
常見的ORM方法
search()
獲取一個搜索域,返回一個匹配記錄的記錄集。可以返回匹配記錄的子集(offset
和limit
參數)並被排序(order參數):
>>> # searches the current model
>>> self.search([('is_company', '=', True), ('customer', '=', True)])
res.partner(7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74)
>>> self.search([('is_company', '=', True)], limit=1).name
'Agrolait'
要檢查任何記錄是否與域相匹配,或者計算記錄的數量,使用searchcount()
create()
獲取許多字段值,並返回一個記錄集,內含的記錄被創建:
>>> self.create({'name': "New Name"})
res.partner(78)
個人測試:
print self.create({'name':'飲水機','employee_id':11,'number':'90876','serial':'az11111','device_status':'normal','category.id':1})
#報錯了
management odoo.sql_db: bad query: INSERT INTO "account_asset_asset" ("id", "method_number", "employee_id", "method_progress_factor", "prorata", "company_id", "device_status", "number", "currency_id", "active", "state", "method_period", "start_date", "date", "method_time", "serial", "method", "name", "create_uid", "write_uid", "create_date", "write_date") VALUES(nextval('account_asset_asset_id_seq'), 5, 11, 0.3, false, 1, 'normal', '90876', 3, true, 'draft', 12, '2018-07-06', '2018-07-06', 'number', 'az11111', 'linear', '飲水機', 1, 1, (now() at time zone 'UTC'), (now() at time zone 'UTC')) RETURNING id
write()
獲取大量的字段值,將它們寫到記錄集中的所有記錄。不返回任何值:
self.write({'name': "Newer Name"})
browse
獲取一個數據庫id或一個ids列表,並返回一個記錄集,當從Odoo外部獲得記錄id時(例如通過外部系統的往返)或在舊API中調用方法時,會很有用:
>>> self.browse([7, 18, 12])
res.partner(7, 18, 12)
exists()
返回一個新的記錄集,其中只包含數據庫中存在的記錄。可以用來檢查記錄(如從外部獲得的)是否仍然存在:
if not record.exists():
raise Exception("The record has been deleted")
或者在調用了一個可以刪除一些記錄的方法之后:
records.may_remove_some()
# only keep records which were not deleted
records = records.exists()
ref()
環境方法返回與提供的外部id匹配的記錄(external id):
>>> env.ref('base.group_public')
res.groups(2)
ensure_one()
檢查記錄集是不是一個單例(只包含一個記錄),否則會產生一個錯誤:
records.ensure_one()
# is equivalent to but clearer than:
assert len(records) == 1, "Expected singleton"
創建模型(Creating Models)
模型字段被定義為模型本身的屬性:
from odoo import models, fields
class AModel(models.Model):
_name = 'a.model.name'
field1 = fields.Char()
警告
這意味着你不能定義一個字段和一個同名的方法,它們會沖突
默認情況下,field的標簽(user-visible name)是字段名的大寫版本,可以用string
參數覆蓋:
field2 = fields.Integer(string="an other field")
對於各種字段類型和參數,請參閱fields引用。
默認值(default)被定義為字段上的參數,或者是值:
a_field = fields.Char(default="a value")
或者調用一個函數來計算默認值,它應該返回那個值:
def compute_default_value(self):
return self.get_value()
a_field = fields.Char(default=compute_default_value)
計算字段(Computed fields)
可以使用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
- 在使用子字段時,依賴項可以是虛線(dotted paths):(dependencies can be dotted paths when using sub-fields:)
@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
參數來啟用計算字段。value是返回一個域的方法名:
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)]
- 為了允許在計算字段上設置值,請使用
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)
- 多個字段可以通過相同的方法同時計算,只需在所有字段上使用相同的方法,並設置所有字段:
- @api.depends
discount_value = fields.Float(compute='_apply_discount')
total = fields.Float(compute='_apply_discount')
@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
關聯字段(Related fields)
計算字段的特殊情況是關聯(代理)字段(related (proxy) fields),它提供了當前記錄下子字段的值。它們的定義是設置related
參數,以及它們可以存儲的常規計算字段:
nickname = fields.Char(related='user_id.partner_id.name', store=True)
onchange:動態更新UI(onchange: updating UI on the fly)
當用戶在表單中改變字段的值時(但還沒有保存表單),根據該值自動更新其他字段可能會很有用,例如,在更改稅或添加新的發票行時更新最終總數。
- 計算字段(computed fields)會自動檢查和重新計算,它們不需要
onchange
- 對於非計算字段,
onchange()
裝飾器用於提供新的字段值:
@api.onchange('field1', 'field2') # if these fields are changed, call method
def check_change(self):
if self.field1 < self.field2:
self.field3 = True
在方法期間執行的更改被發送到客戶端程序,並對用戶可見
- 計算字段和new-API
onchanges
都是由客戶端自動調用的,而無需在視圖中添加它們 - 可以通過在視圖中添加
onchange="0"
來抑制來自特定字段的觸發器:
<field name="name" on_change="0"/>
當用戶編輯字段時,即使有功能字段或顯式的onchange,也不會觸發任何接口更新。(添加了onchange="0"
,不會觸發字段更新)
onchange方法對這些記錄的虛擬記錄分配工作沒有寫到數據庫中,只是用來了解要返回給客戶的值
警告
對於一個one2many
或者many2many
領域來說,通過onchange來修改自身是不可能的。這是一個webclient限制-參見#2693。
低級的SQL(Low-level SQL)
環境中的cr
屬性是當前數據庫事務的游標,並且允許直接執行SQL,或者用於難以用ORM來表達的查詢(例如復雜連接),或者出於性能方面的原因:
self.env.cr.execute("some_sql", param1, param2, param3)
由於模型使用相同的游標,並且Environment
持有不同的緩存,所以當在原始SQL中更改數據庫時,這些緩存必須失效,否則模型的進一步使用可能會變得不連貫。有必要在SQL中使用CREATE
、UPDATE
或DELETE
時清除緩存,而不是SELECT
(只需讀取數據庫即可)。
清除緩存可以使用Environment
對象的invalidate_all()
方法來執行。
新API與舊API之間的兼容性(Compatibility between new API and old API)
Odoo目前正從一個較老的(不是很正規的)API過渡,它可能需要手動地從一個到另一個的連接:
- RPC層(XML-RPC和JSON-RPC)都是用舊的API來表達的,純粹在新API中表達的方法在RPC上是不可用的。
- 可覆蓋的方法可以從舊的代碼中調用,這些代碼仍然是用舊的API樣式編寫的
舊的和新的api之間的巨大差異是:
Environment
的值(游標、用戶id和上下文)被顯式地傳遞給方法- 記錄數據(
ids
)被顯式地傳遞給方法,並且可能根本沒有通過。 - 方法傾向於使用id列表而不是記錄集
默認情況下,方法被假定使用新的API樣式,並且不能從舊的API樣式調用。
新API調用舊API的調用被橋接
當使用新的API樣式時,對使用舊API定義的方法的調用會自動轉換,不需要做任何特別的事情:
>>> # method in the old API style
>>> def old_method(self, cr, uid, ids, context=None):
... print ids
>>> # method in the new API style
>>> def new_method(self):
... # system automatically infers how to call the old-style
... # method from the new-style method
... self.old_method()
>>> env[model].browse([1, 2, 3, 4]).new_method()
[1, 2, 3, 4]
兩個裝飾器可以將一種新型的方法暴露給舊的API:
model()
該方法是在不使用ids的情況下公開的,它的記錄集通常是空的。它的“舊API”簽名是cr
、uid
、*arguments
, context
:
@api.model
def some_method(self, a_value):
pass
# can be called as
old_style_model.some_method(cr, uid, a_value, context=context)
multi()
這個方法被公開為獲取一個ids列表(可能是空的),它的“舊API”簽名是cr
、uid
、id
、*arguments
, context
:
@api.multi
def some_method(self, a_value):
pass
# can be called as
old_style_model.some_method(cr, uid, [id1, id2], a_value, context=context)
因為新型的api傾向於返回記錄集,而舊式的api傾向於返回ids列表,還有一個裝飾器管理着:
returns()
這個函數被假定返回一個記錄集,第一個參數應該是記錄集的模型或self
的名稱(對於當前的模型)。
如果這種方法在新的API風格中被調用,則不會產生任何影響,但是當從舊的API樣式調用時,將記錄集轉換為id列表:
>>> @api.multi
... @api.returns('self')
... def some_method(self):
... return self
>>> new_style_model = env['a.model'].browse(1, 2, 3)
>>> new_style_model.some_method()
a.model(1, 2, 3)
>>> old_style_model = pool['a.model']
>>> old_style_model.some_method(cr, uid, [1, 2, 3], context=context)
[1, 2, 3]
參考模型(Model Reference)
class odoo.models.Model(pool, cr)
用於常規數據庫的主超級類。
Odoo的模型是通過繼承這個類來創建的:
class user(Model):
...
該系統稍后將實例化每個數據庫(安裝類模塊)的類。
結構屬性(Structural attributes)
_name
業務對象名稱,在點符號(在模塊名稱空間中)
_rec_name
使用名稱的替代字段,osv的name _get()
(默認:'name'
)
_inherit
如果_name
被設置,則繼承父模型的名稱。可以是一個str
如果繼承了單一父節點
如果_name
是未設置的,則可以將單個模型的名稱擴展到該模型內
參考繼承與擴展
_order
在沒有指定順序的情況下進行搜索的排序字段(默認:'id'
)
_auto
是否應該創建一個數據庫表(默認值:
True
)
如果設置為False
,覆蓋init()
來創建數據庫表
要創建一個沒有任何表的模型,可以從
odoo.model.abstractmodel
繼承。
_table
默認情況下自動生成的模型的表的名稱。
_inherits
字典將父業務對象的名稱映射到要使用的相應外鍵字段的名稱:
_inherits = {
'a.model': 'a_field_id',
'b.model': 'b_field_id'
}
實現基於組合的繼承:新模型公開了_inherits
模型的所有字段,但沒有存儲它們:這些值本身仍然存儲在鏈接的記錄中。
警告
是否同一個字段是在多個繼承的基礎上定義的
_constraints
定義Python約束的(constraint_function
, message
, fields
)列表。字段列表是指示性的
自版本8:使用constrains()
_sql_constraints
列出(name
, sql_definition
, message
)的三元組,定義SQL約束,以便在生成后備表時執行
_parent_store
除了parent_left
和parent_right
,設置一個嵌套集,以便在當前模型的記錄上啟用快速層次查詢(默認為False
)
Type: bool
CRUD
create(vals) → record
為模型創建一個新的記錄。
新的記錄使用來自於valS
的值和來自default_get()
的值來初始化。
參數: vals (dict) :模型字段的值,作為字典:
有關詳細信息,請參write()
返回值: 新的記錄被創建
Raises
AccessError –
if user has no create rights on the requested object
if user tries to bypass access rules for create on the requested object
如果用戶在被請求的對象上沒有創建權限
如果用戶試圖繞過在被請求對象上創建的訪問規則
ValidateError – if user tries to enter invalid value for a field that is not in selection
如果用戶試圖為一個不在選擇中的字段輸入無效值
UserError – if a loop would be created in a hierarchy of objects a result of the operation (such as setting an object as its own parent)
如果一個循環將在對象的層次結構中創建,這是操作的結果(例如將對象設置為其母公司)
browse([ids]) → records
在當前環境中為作為參數提供的ids返回一個記錄集。
不能使用任何ids、單個id或一系列ids。
unlink()
刪除當前集合的記錄
Raises
AccessError –
if user has no unlink rights on the requested object
if user tries to bypass access rules for unlink on the requested object
如果用戶在被請求的對象上沒有unlink權限
如果用戶試圖繞過被請求對象上的unlink的訪問規則
UserError – if the record is default property for other records
如果記錄是其他記錄的默認屬性
write(vals)
用所提供的值更新當前集合中的所有記錄。
參數: vals (dict)
要更新的字段和設置的值
{'foo': 1, 'bar': "Qux"}
如果這些是有效的(否則它將觸發一個錯誤),將把field foo
設置為1
,並將field bar
設置為“Qux”
。
Raises
AccessError –
if user has no write rights on the requested object
if user tries to bypass access rules for write on the requested object
如果用戶在被請求的對象上沒有寫權限
如果用戶試圖繞過訪問規則,以便在被請求的對象上書寫
ValidateError – if user tries to enter invalid value for a field that is not in selection
如果用戶試圖為一個不在選擇中的字段輸入無效值
UserError – if a loop would be created in a hierarchy of objects a result of the operation (such as setting an object as its own parent)
如果一個循環將在對象的層次結構中創建,這是操作的結果(例如將對象設置為其母公司)
- 對於數字字段(
Integer, Float
),值應該是對應類型的值 - 對於
Boolean
來說,值應該是bool
- 對於
Selection
,值應該與選擇值相匹配(通常是str
,有時是int
) - 對於
Many2one
來說,值應該是設置記錄的數據庫標識符 - 其他非關系字段使用字符串作為值
危險
出於歷史和兼容性的原因,Date
和Datetime
字段使用字符串作為值(書面和讀取),而不是date
或datetime
。這些日期字符串是utc,並根據odoo.tools.misc.DEFAULT_SERVER_DATE_FORMAT
和odoo.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT
One2many
和Many2many
使用一種特殊的“命令”格式來操作與該字段相關聯的一組記錄。
這種格式是按順序執行的三胞胎列表,其中每一個triplet都是在記錄集上執行的命令。並不是所有的命令都適用於所有情況。可能的命令是:
(0, _, values)
添加一個從提供的value
中創建的新記錄。
(1, id, values)
用values
的值更新id id
的現有記錄。不能在create()
中使用。
(2, id, _)
從集合中刪除id id
的記錄,然后刪除它(來自數據庫)。不能在create()
中使用。
(3, id, _)
從集合中刪除id id
的記錄,但不會刪除它。不能用在One2many
上。不能在create()
中使用。
(4, id, _)
將id id
的現有記錄添加到集合中。不能在One2many
上使用。
(5, _, _)
從集合中刪除所有記錄,相當於在每個記錄上顯式地使用命令3
。不能用在One2many
上。不能在create()
中使用。
(6, _, ids)
用ids
列表替換集合中所有現有的記錄,相當於使用命令5
,然后在ids
中為每個id
執行命令4
。
在上面的列表中標記
_
的值被忽略,可以是任何東西,通常是0
或False
。
read([fields])
在self
、low-level/rpc方法中讀取所請求的字段。在Python代碼中,更喜歡browse()
。
Parameters fields – list of field names to return (default is all fields)
返回的字段名列表(默認為所有字段)
Returns a list of dictionaries mapping field names to their values, with one dictionary per record
一列字典將字段名映射到它們的值,每個記錄有一個字典
Raises AccessError – if user has no read rights on some of the given records
如果用戶對某些記錄沒有讀權限
read_group(domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True)
獲取列表視圖中的記錄列表,按給定的groupby
字段分組
Parameters
domain – list specifying search criteria [[‘field_name’, ‘operator’, ‘value’], …] 列表中指定搜索條件[[‘field_name’, ‘operator’, ‘value’],…]
fields (list) – list of fields present in the list view specified on the object 在對象上指定的列表視圖中顯示的字段列表
groupby (list) – list of groupby descriptions by which the records will be grouped. A groupby description is either a field (then it will be grouped by that field) or a string ‘field:groupby_function’. Right now, the only functions supported are ‘day’, ‘week’, ‘month’, ‘quarter’ or ‘year’, and they only make sense for date/datetime fields. 按組的描述,記錄將被分組。一個群的描述要么是一個字段(然后它將被該字段分組)或一個字符串'field:groupby_function'。目前,唯一支持的功能是‘day’, ‘week’, ‘month’, ‘quarter’ or ‘year’,它們只對date/datetime字段有意義。
offset (int) – optional number of records to skip 可選的記錄數量
limit (int) – optional max number of records to return 可選的最大記錄數
orderby (list) – optional order by specification, for overriding the natural sort ordering of the groups, see also search() (supported only for many2one fields currently) 按規范的可選順序,為了覆蓋組的自然排序順序,請參閱search()(目前只支持許多21個字段)
lazy (bool) – if true, the results are only grouped by the first groupby and the remaining groupbys are put in the __context key. If false, all the groupbys are done in one call.
如果是TRUE,那么結果只會被第一個groupby分組,剩下的groupbys將被放在_context鍵中。如果是False,所有的組都是在一個調用中完成的
Returns
list of dictionaries(one dictionary for each record) containing:
字典列表(每個記錄的一個字典)包含:
the values of fields grouped by the fields in groupby argument
字段按組群分組的字段值
__domain: list of tuples specifying the search criteria 指定搜索條件的元組列表
__context: dictionary with argument like groupby 像groupby這樣的參數字典
Return type :[{‘field_name_1’: value, ..]
Raises: AccessError –
if user has no read rights on the requested object
如果用戶在被請求的對象上沒有讀權限
if user tries to bypass access rules for read on the requested object
如果用戶試圖繞過訪問規則來讀取所請求的對象
查詢(Searching)
search(args[, offset=0][, limit=None][, order=None][, count=False])
搜索基於args
搜索域的記錄。
Parameters:
args – A search domain. Use an empty list to match all records. 一個搜索領域。使用空鏈表來匹配所有記錄。
offset (int) – number of results to ignore (default: none)
忽略的結果數(默認值:none)
limit (int) – maximum number of records to return (default: all) 要返回的記錄的最大數目(默認值:all)
order (str) – sort string 排序字符串
count (bool) – if True, only counts and returns the number of matching records (default: False) 如果是True,只計算並返回匹配記錄的數量(默認:False)
Returns: at most limit records matching the search criteria 在大多數限制與搜索條件匹配的記錄
Raises: AccessError –
if user tries to bypass access rules for read on the requested object. 如果用戶試圖繞過訪問規則,以便在被請求的對象上閱讀。
search_count(args) → int
如果用戶試圖繞過訪問規則,以便在被請求的對象上閱讀。
name_search(name='', args=None, operator='ilike', limit=100) → records
與給定的operator
相比,搜索具有與給定name
模式匹配的顯示名稱的記錄,同時還匹配可選搜索域(args
)。
例如,它用於提供基於關系字段的部分值的建議。有時被看作是name_get()
的逆函數,但它不能保證是。
這個方法相當於調用search()
,它的搜索域基於display_name
,然后在搜索結果上的name_get()
。
Parameters:
name (str) – the name pattern to match 匹配的名稱模式
args (list) – optional search domain (see search() for syntax), specifying further restrictions 可選的搜索域(參見search()語法),指定進一步的限制
operator (str) – domain operator for matching name, such as 'like' or '='. 域名操作符匹配名稱,如“like”或“=”。
limit (int) – optional max number of records to return 可選的最大記錄數
Return type: list 列表
Returns: list of pairs (id, text_repr) for all matching records.所有匹配記錄的成對列表(id,text_repr)。
記錄集操作(Recordset operations)
ids
在這個記錄集中的實際記錄ids列表(忽略記錄創建的占位符ids)
ensure_one()
驗證當前記錄集保存單個記錄。提出了一個例外。
exists() → records
返回存在的self
記錄的子集,並在緩存中標記刪除記錄。它可以作為記錄的測試:
if record.exists():
...
按照慣例,新的記錄將作為現有的記錄返回。
filtered(func)
選擇self
的記錄,這樣func(rec)
是正確的,並將它們作為記錄集返回。
Parameters: func – a function or a dot-separated sequence of field names
一個函數或一個點分隔的字段名序列
sorted(key=None, reverse=False)
返回按key
排序的記錄集self
。
Parameters:
key – either a function of one argument that returns a comparison key for each record, or a field name, or None, in which case records are ordered according the default model’s order 要么是一個參數的函數,它返回每個記錄的比較key,或者一個字段名,或者為None,在這種情況下,根據默認模型的順序排列記錄
reverse – if True, return the result in reverse order 如果是真的,則以相反的順序返回結果
mapped(func)
將func
應用於self
的所有記錄,並將結果作為列表或記錄集返回(如果func
返回記錄集)。在后一種情況下,返還記錄集的順序是任意的。
Parameters func – a function or a dot-separated sequence of field names (string); any falsy value simply returns the recordset
self
一個函數或一個點分隔的字段名稱序列(字符串);任何falsy的值都只返回記錄集的“self”
環境切換(Environment swapping)
sudo([user=SUPERUSER])
返回給所提供的用戶的這個記錄集的新版本。
默認情況下,這會返回一個超級用戶SUPERUSER
記錄集,其中訪問控制和記錄規則被忽略。
使用
sudo
可能導致數據訪問跨越記錄規則的邊界,可能混合了被隔離的記錄(例如,在多公司環境中來自不同公司的記錄)。
它可能會導致不直觀的結果,在許多方法中選擇一個記錄——例如,獲得默認的公司,或者選擇一個材料清單。
with_context([context][, **overrides]) → records
返回一個附加到擴展上下文的記錄集的新版本。
擴展的context要么提供的overrides
的context
被合並,要么當前context
被overrides
的被合並,例如:
# 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_env(env)
返回一個附加到所提供環境的新版本的記錄集
警告
新環境不會從當前環境的數據緩存中受益,因此以后的數據訪問可能會在從數據庫重新取回時產生額外的延遲。返回的記錄集具有與self
相同的預取對象。
- 個人注記:切換環境就是放棄原來的緩存數據,因為odoo訪問數據庫,訪問一次后會存儲緩存,切換環境為了避免原來的緩存
字段和視圖查詢(Fields and views querying)
fields_get([fields][, attributes])
返回每個字段的定義。
返回的值是字典中的(用字段名表示)字典。包括_inherits’d的字段。string, help, and selection (if present) 屬性被翻譯。
Parameters:
allfields – list of fields to document, all if empty or not provided
文件的字段列表,如果沒有提供,所有的字段都是空的
attributes – list of description attributes to return for each field, all if empty or not provided
為每個字段返回的描述屬性列表,全部如果空或未提供
fields_view_get([view_id | view_type='form'])
獲得所請求視圖的詳細組成,如字段、模型、視圖架構
Parameters:
view_id – id of the view or None 視圖的id或None
view_type – type of the view to return if view_id is None (‘form’, ‘tree’, …) 如果viewid是None('form','tree',…)的視圖類型。
toolbar – true to include contextual actions 確實包括上下文動作
submenu – deprecated 不推薦使用
Returns: dictionary describing the composition of the requested view (including inherited views and extensions) 描述被請求視圖的組成(包括繼承的視圖和擴展)的字典
Raises:
AttributeError –
if the inherited view has unknown position to work with other than ‘before’, ‘after’, ‘inside’, ‘replace’
如果繼承的視圖有未知的位置可以與‘before’, ‘after’, ‘inside’, ‘replace’一起工作
if some tag other than ‘position’ is found in parent view
如果在父視圖中發現了“位置”以外的一些標記1
Invalid ArchitectureError – if there is view type other than form, tree, calendar, search etc defined on the structure 如果在結構上定義了視圖類型,而不是表單、樹、日歷、搜索等
雜項工具(各種各樣的方法)(Miscellaneous methods)
default_get(fields) → default_values
返回fields_list
中的字段的默認值。默認值由上下文、用戶違約和模型本身決定。
Parameters:
fields_list – a list of field names 字段名列表
Returns a dictionary mapping each field name to its corresponding default value, if it has one. 如果有一個字典,將每個字段名映射到對應的默認值。
copy(default=None)
重復記錄self
更新它的默認值
Parameters
default (dict) – dictionary of field values to override in the original values of the copied record, e.g: {'field_name': overridden_value, ...}
在復制記錄的原始值中覆蓋字段值的字典, e.g: {'field_name': overridden_value, ...}
Returns: new record
name_get() → [(id, name), ...]
返回self
中的記錄的文本表示法。默認情況下,這是display_name
字段的值。
Returns: list of pairs (
id, text_repr
) for each records 對每個記錄的成對列表(“id,text_repr”)
Return type:list(tuple)
name_create(name) → record
通過調用create()
來創造一個新的記錄,只提供一個值:新記錄的顯示名稱。
新的記錄將使用任何適用於該模型的默認值進行初始化,或者通過context提供。create()
通常的行為是適用的。
Parameters:
name – display name of the record to create 顯示創建記錄的名稱
Return type:tuple
Returns: the name_get() pair value of the created record 所創建記錄的name_get()配對值
自動字段(Automatic fields)
id
定義字段id
_log_access
日志訪問字段(create_date、write_uid、…)是否應該生成(默認:True)
create_date
創建記錄的日期
Type :Datetime
create_uid
創建記錄的用戶的關系字段
Type: res.users
write_date
記錄最后一次修改的日期
Type: Datetime
write_uid
對最后一個修改記錄的用戶的關系字段
Type: res.users
保留字段名稱
一些字段名被預留給預先定義的行為,超出了自動化字段的范圍。當需要相關的行為時,應該在模型上定義它們:
name
_rec_name
的默認值,用於在需要有代表性的“naming”的context顯示記錄。
Type: Char
active
如果active
被設置為False
,那么在大多數搜索和列表中,記錄是不可見的。
Type: Boolean
sequence
可修改的排序標准,允許在列表視圖中對模型進行拖放重新排序
Type: Integer
state
對象的生命周期階段,由各state
屬性在字段上使用
Type: Selection
parent_id
用於在樹狀結構中訂單記錄,並支持域內的child of
操作員
Type: Many2one
parent_left
用於_parent_store
,允許更快的樹結構訪問
parent_right
詳見parent_right
方法裝飾器(Method decorators)
這個模塊提供了管理兩種不同API風格的元素,即“traditional”和“record”樣式。
在“traditional”樣式中,諸如database cursor(數據庫游標), user id(用戶id), context dictionary(上下文字典) 和record ids(記錄ids)(通常表示為cr、uid、context、id)等參數被顯式地傳遞給所有方法。在“record”樣式中,這些參數隱藏在模型實例中,這使它具有更面向對象的感覺。
例如,語句:
model = self.pool.get(MODEL)
ids = model.search(cr, uid, DOMAIN, context=context)
for rec in model.browse(cr, uid, ids, context=context):
print rec.name
model.write(cr, uid, ids, VALUES, context=context)
也可以寫成:
env = Environment(cr, uid, context) # cr, uid, context wrapped in env
model = env[MODEL] # retrieve an instance of MODEL
recs = model.search(DOMAIN) # search returns a recordset
for rec in recs: # iterate over the records
print rec.name
recs.write(VALUES) # update all records in recs
用“traditional”風格編寫的方法會自動修飾,遵循一些基於參數名的啟發式。
odoo.api.multi(method)
裝飾一個記錄風格的方法,self
是一個記錄集。這個方法通常定義一個記錄上的操作。這樣一個方法:
@api.multi
def method(self, args):
...
可以在記錄和傳統風格中被調用,比如:
# recs = model.browse(cr, uid, ids, context)
recs.method(args)
model.method(cr, uid, ids, args, context=context)
odoo.api.model(method)
裝飾一種記錄式的方法,自我是一個記錄集,但它的內容是不相關的,只有模型是。這樣一個方法:
@api.model
def method(self, args):
...
可以在記錄和傳統風格中被調用,比如:
# recs = model.browse(cr, uid, ids, context)
recs.method(args)
model.method(cr, uid, args, context=context)
請注意,沒有任何ids以傳統的方式傳遞給該方法。
odoo.api.depends(*args)
返回一個裝飾器,它指定了“compute”方法(用於新型功能字段)的字段依賴項。每一個參數都必須是一個字符串,它由一個點分隔的字段名序列組成:
pname = fields.Char(compute='_compute_pname')
@api.one
@api.depends('partner_id.name', 'partner_id.is_company')
def _compute_pname(self):
if self.partner_id.is_company:
self.pname = (self.partner_id.name or "").upper()
else:
self.pname = self.partner_id.name
你也可以把一個函數作為參數傳遞。在這種情況下,依賴關系是通過調用field模型的函數來給出的。
odoo.api.constrains(*args)
裝飾約束檢查。每個參數必須是檢查中使用的字段名:
@api.one
@api.constrains('name', 'description')
def _check_description(self):
if self.name == self.description:
raise ValidationError("Fields name and description must be different")
在已被修改的指定字段的記錄上調用。
如果驗證失敗,會引起ValidationError
。
警告
@constrains
只支持簡單的field names(字段名),dotted names (點名)(關系字段的字段,例如partnerid.customer
)不受支持,並且將被忽略。
只有在修飾方法中聲明的字段包含在
create
或write
調用中,才會觸發@constrains
。它意味着在一個視圖中不存在的字段不會在創建記錄時觸發調用。為了確保始終會觸發一個約束(例如測試沒有值),必須重寫create
。
odoo.api.onchange(*args)
返回裝飾器來裝飾給定字段的onchange方法。每個參數必須是一個字段名:
@api.onchange('partner_id')
def _onchange_partner(self):
self.message = "Dear %s" % (self.partner_id.name or "")
在字段出現的表單視圖中,當一個給定的字段被修改時,該方法將被調用。這個方法是在一個偽記錄上被調用的,這個偽記錄包含表單中存在的值。該記錄上的字段分配會自動發送回客戶端。
這個方法可以返回一個字典來改變字段域,並彈出一個警告消息,就像在舊的API中一樣:
return {
'domain': {'other_id': [('partner_id', '=', partner_id)]},
'warning': {'title': "Warning", 'message': "What is this?"},
}
警告
@onchange
只支持簡單的字段名,虛線名(如partnerid.tz
)的字段名不受支持,將被忽略。
odoo.api.returns(model, downgrade=None, upgrade=None)
返回裝飾器返回模型實例的方法。
Parameters:
model: – a model name, or 'self' for the current model 模型名稱或當前模型名稱‘self’
downgrade: – a functiondowngrade(self, value, *args, **kwargs)
to convert the record-style value to a traditional-style output 將記錄樣式的值轉化到傳統樣式的輸出
upgrade: – a functionupgrade(self, value, *args, **kwargs)
to convert the traditional-style value to a record-style output 將傳統樣式的值轉化為記錄樣式輸出
參數self
、*args
和**kwargs
是在記錄樣式中傳遞給該方法的參數。
裝飾器將方法輸出調整到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)
請注意,裝飾方法必須滿足該約定。
這些修飾符是自動繼承的:覆蓋修飾過的現有方法的方法將使用相同的@returns(model)
來裝飾。
odoo.api.one(method)
(已棄用)
裝飾一個記錄樣式的方法,在這個方法中,self
被期望是一個單例實例。修飾的方法會自動在記錄上循環,並使用結果列出一個列表。如果方法使用returns()
來裝飾,則會將產生的實例連接起來。如下列方法:
@api.one
def method(self, args):
return self.name
可以在記錄和傳統風格中被調用,比如:
# recs = model.browse(cr, uid, ids, context)
names = recs.method(args)
names = model.method(cr, uid, ids, args, context=context)
自版本9.0棄用以來:one()
,棄用的代碼常常使代碼不那么清晰,並且以開發人員和讀者可能想不到的方式表現出來。
強烈建議使用multi()
,並在self
記錄集上進行迭代,或者確保記錄集是帶有ensure_one()的單個記錄。
odoo.api.v7(method_v7)
只支持舊式api的方法。一種新型的api可以通過重新定義具有相同名稱的方法來提供,並使用v8()
進行修飾:
@api.v7
def foo(self, cr, uid, ids, context=None):
...
@api.v8
def foo(self):
...
如果一種方法調用另一個方法,則必須特別小心,因為該方法可能會被覆蓋!在這種情況下,應該從當前類(比如MyClass
)調用該方法,例如:
@api.v7
def foo(self, cr, uid, ids, context=None):
# Beware: records.foo() may call an overriding of foo()
records = self.browse(cr, uid, ids, context)
return MyClass.foo(records)
注意裝飾器方法使用第一個方法的docstring。
odoo.api.v8(method_v8)
僅對新型api的裝修方法進行修飾。一個舊式的api可以通過重新定義一個同名的方法來提供,並使用v7()進行修飾:
@api.v8
def foo(self):
...
@api.v7
def foo(self, cr, uid, ids, context=None):
...
注意裝飾器方法使用第一個方法的docstring。
字段(Fields)
基礎字段(Basic fields)
class odoo.fields.Field(string=<object object>, **kwargs)
字段描述符包含字段定義,並管理記錄上相應字段的存取和賦值。當一個字段的立即執行時,可以提供以下屬性:
Parameters:
string: – the label of the field seen by users (string); if not set, the ORM takes the field name in the class (capitalized). 用戶看到的字段的標簽(字符串);如果沒有設置,ORM就會在類中獲取字段名(大寫)。
help – the tooltip of the field seen by users (string) 用戶看到的字段的提示(字符串)
readonly – whether the field is readonly (boolean, by default False) 字段是否為readonly(布爾值,默認為False
)
required – whether the value of the field is required (boolean, by default False) 是否需要字段的值(布爾值,默認為False
)
index – whether the field is indexed in database (boolean, by default False) 字段是否在數據庫中被索引(布爾值,默認為False
)
default – the default value for the field; this is either a static value, or a function taking a recordset and returning a value; use default=None to discard default values for the field
該字段的缺省值;這是一個靜態值,或者是一個使用記錄集並返回一個值的函數;使用default=None
取消字段的默認值
states – a dictionary mapping state values to lists of UI attribute-value pairs; possible attributes are: ‘readonly’, ‘required’, ‘invisible’. Note: Any state-based condition requires thestate
field value to be available on the client-side UI. This is typically done by including it in the relevant views, possibly made invisible if not relevant for the end-user.
字典將狀態值映射到UI屬性-值對列表;可能的屬性是:‘readonly’, ‘required’, ‘invisible’。注意:任何基於狀態的條件都需要在客戶端UI上提供state
字段值。這通常是通過將其包含在相關視圖中來完成的,可能是不可見的,如果與最終用戶無關的話
groups – comma-separated list of group xml ids (string); this restricts the field access to the users of the given groups only
逗號分隔的組xml ids列表(字符串);這限制了只對給定組的用戶進行字段訪問
copy (bool) – whether the field value should be copied when the record is duplicated (default: True for normal fields, False for one2many and computed fields, including property fields and related fields)
當記錄被復制時,是否應該復制字段值(默認情況:True
值用於正常字段來,False
值用於one2many
和計算字段,包括屬性字段和相關字段)
oldname (string) – the previous name of this field, so that ORM can rename it automatically at migration 這個字段的前一個名稱,以便ORM可以在遷移時自動重命名它
計算字段(Computed fields)
你可以定義一個值被計算的字段,而不是簡單地從數據庫中讀取。下面給出了特定於計算字段的屬性。要定義這樣的字段,只需為屬性compute
提供一個值。
Parameters:
compute – name of a method that computes the field 計算該字段的方法的名稱
inverse – name of a method that inverses the field (optional) 反向字段(可選)的方法的名稱
search – name of a method that implement search on the field (optional)
在字段實現搜索的方法的名稱(可選)
store – whether the field is stored in database (boolean, by default False on computed fields) 字段是否存儲在數據庫中(布爾值,默認情況下False在計算字段上)
compute_sudo – whether the field should be recomputed as superuser to bypass access rights (boolean, by default False)
該字段是否應該重新計算為超級用戶,以繞過訪問權限(布爾值,默認為False)
compute
, inverse
and search
的方法是模型方法。他們的簽名如下面的例子所示:
upper = fields.Char(compute='_compute_upper',
inverse='_inverse_upper',
search='_search_upper')
@api.depends('name')
def _compute_upper(self):
for rec in self:
rec.upper = rec.name.upper() if rec.name else False
def _inverse_upper(self):
for rec in self:
rec.name = rec.upper.lower() if rec.upper else False
def _search_upper(self, operator, value):
if operator == 'like':
operator = 'ilike'
return [('name', operator, value)]
計算方法必須在被調用的記錄集中的所有記錄上指定字段。裝飾器odoo.api.depends()
必須應用於計算方法,以指定字段依賴項;這些依賴關系用於確定何時重新計算字段;重新計算是自動的,並保證緩存/數據庫的一致性。請注意,同樣的方法可以用於幾個字段,您只需分配方法中的所有給定字段;該方法將在所有的這些字段中被調用一次。
默認情況下,計算字段不會存儲到數據庫中,並且是動態計算的。添加屬性store=True
將把字段的值存儲在數據庫中。存儲字段的優點是,在該字段上進行搜索是由數據庫本身完成的。缺點是,當字段必須重新計算時,它需要數據庫更新。
inverse方法,如其名稱所示,是計算方法的倒數:被調用的記錄對字段有一個值,並且您必須在字段依賴項上應用必要的更改,以便計算給出預期的值。注意,沒有inverse方法的計算字段在默認情況下是readonly。
在對模型進行實際搜索之前,當處理域時調用search方法。它必須返回一個域相同的條件:field operator value(字段操作值)
關聯字段(Related fields)
關聯字段的值是通過一系列關聯字段和在接近的模型讀取字段。要遍歷的字段的完整序列是由屬性指定的
Parameters:
related – sequence of field names 一系列字段名稱
如果沒有重新定義的話,一些字段屬性會自動從源字段中復制:string
, help
, readonly
, required
(只有在需要序列中的所有字段時才需要)、groups
, digits
, size
, translate
, sanitize
, selection
, comodel_name
, domain
, context
。所有的語義不相關的屬性都是從源字段中復制的。
默認情況下,相關字段的值不會存儲到數據庫中。添加屬性store=True
來使其存儲,就像計算字段一樣。當相關性被修改時,相關字段會自動重新計算。
公司依賴字段(Company-dependent fields)
以前被稱為“property”字段,這些字段的價值取決於公司。換句話說,屬於不同公司的用戶在給定的記錄中可能會看到該字段的不同值。
Parameters:
company_dependent – whether the field is company-dependent (boolean)
字段是否是公司依賴值(boolean)
增量定義(Incremental definition)
字段被定義為model類上的class屬性。如果模型被擴展(參見Model),您還可以通過重新定義一個同名的字段來擴展字段定義,並在子類中定義相同的類型。在這種情況下,字段的屬性取自父類,並由子類中給出的屬性覆蓋。
例如,下面的第二個類只會在字段state
上添加一個提示:
class First(models.Model):
_name = 'foo'
state = fields.Selection([...], required=True)
class Second(models.Model):
_inherit = 'foo'
state = fields.Selection(help="Blah blah blah")
Char
class odoo.fields.Char(string=<object object>, **kwargs)
基類:odoo.fields._String
基本的字符串字段,可以是長度限制的,通常在客戶端顯示為單行字符串。
Parameters:
size (int) – the maximum size of values stored for that field
存儲該字段的最大值的最大值
translate – enable the translation of the field’s values; use translate=True to translate field values as a whole; translate may also be a callable such that translate(callback, value) translates value by using callback(term) to retrieve the translation of terms.
允許翻譯字段的值;使用translate=True
將字段值轉換為一個整體;translate
也可以是一個可調用的函數,類似translate(callback, value)
翻譯通過使用callback(term)
獲取翻譯的條目的value
Boolean
class odoo.fields.Boolean(string=<object object>, **kwargs)
基類:odoo.fields.Field
Float
class odoo.fields.Float(string=<object object>, digits=<object object>, **kwargs)
基類: odoo.fields.Field
精度數字是由屬性給出的
Parameters:
digits – a pair (total, decimal), or a function taking a database cursor and returning a pair (total, decimal)
一對(總數,十進制),或者一個函數,取一個數據庫游標並返回一對(總數,小數)
Text
class odoo.fields.Text(string=<object object>, **kwargs)
基類:Bases: odoo.fields._String
與Char
非常相似,但用於較長的內容,沒有大小,通常顯示為多行文本框。
Parameters
translate – enable the translation of the field’s values; use translate=True to translate field values as a whole; translate may also be a callable such that translate(callback, value) translates value by using callback(term) to retrieve the translation of terms.
允許翻譯字段的值;使用translate=True
將字段值轉換為一個整體;translate
也可以是一個可調用的函數,類似translate(callback, value)
翻譯通過使用callback(term)
獲取翻譯的條目的value
Selection
class odoo.fields.Selection(selection=<object object>, string=<object object>, **kwargs)
基類:Bases: odoo.fields.Field
Parameters
selection – specifies the possible values for this field. It is given as either a list of pairs (value, string), or a model method, or a method name.
指定該字段的可能值。它被作為成對的列表(值,字符串),或者一個模型方法,或者一個方法名。
selection_add – provides an extension of the selection in the case of an overridden field. It is a list of pairs (value, string).
在覆蓋字段的情況下提供選擇的擴展。它是一對對(值,字符串)的列表。
屬性selection
是強制性的,除非是相關字段或字段擴展名。
Html
class odoo.fields.Html(string=<object object>, **kwargs)
基類: odoo.fields._String
Date
class odoo.fields.Date(string=<object object>, **kwargs)
基類: odoo.fields.Field
static context_today(timestamp=None)
以格式化的樣式或者日期字段返回在客戶的時區中看到的當前日期。這個方法可以用來計算默認值。
Parameters:
timestamp (datetime
) – optional datetime value to use instead of the current date and time (must be a datetime, regular dates can’t be converted between timezones.)
可選的datetime值代替當前日期和時間(必須是datetime,常規日期不能在時區之間轉換)。
Return type :str
返回類型字符串
static from_string()
將ORMvalue
轉換為date
值。
static to_string()
將date
值轉換為ORM所期望的格式。
static today()
以ORM期望的格式返回當前的日期。這個函數可以用來計算默認值。
Datetime
class odoo.fields.Datetime(string=<object object>, **kwargs)
基類:odoo.fields.Field
static context_timestamp(timestamp)
返回給定時間戳轉換為客戶端的時區。這種方法不適合作為默認的初始化器,因為datetime字段會在客戶端顯示時自動轉換。對於默認值fields.datetime.now()
應該使用。
Parameters
timestamp (datetime
) – naive datetime value (expressed in UTC) to be converted to the client timezone
原始的datetime值(在UTC中表示)被轉換為客戶端時區
Return type datetime
Returns 時間戳在context時區轉換為timezone-aware datetime
static from_string()
將ORMvalue
轉換為date
值。
static now()
以ORM期望的格式返回當前的日期和時間。這個函數可以用來計算默認值。
static to_string()
將datetime
值轉換為ORM所期望的格式。
關系字段(Relational fields)
Many2one
class odoo.fields.Many2one(comodel_name=<object object>, string=<object object>, **kwargs)
基類:odoo.fields._Relational
這樣一個字段的值是一個長度為0(沒有記錄)或1(單個記錄)的記錄集。
Parameters:
comodel_name – name of the target model (string)
目標模型的名稱(字符串)
domain – an optional domain to set on candidate values on the client side (domain or string)
在客戶端(域或字符串)上設置候選值的可選域
context – an optional context to use on the client side when handling that field (dictionary)
在處理該字段時在客戶端使用的可選上下文(dictionary)
ondelete – what to do when the referred record is deleted; possible values are: 'set null', 'restrict', 'cascade'
當被引用的記錄被刪除時該怎么辦;可能的值是:'set null
', 'restrict
', 'cascade
'
auto_join – whether JOINs are generated upon search through that field (boolean, by default False)
是否通過該字段進行搜索(boolean,默認為False
)
delegate – set it to True to make fields of the target model accessible from the current model (corresponds to _inherits)
將其設置為True
,使目標模型的字段可從當前模型中訪問(對應於_inherits
)
除了相關字段或字段擴展的情況外,屬性comodel_name
是強制性的。
One2many
class odoo.fields.One2many(comodel_name=<object object>, inverse_name=<object object>, string=<object object>, **kwargs)
基類:odoo.fields._RelationalMulti
One2many字段;這樣一個字段的值是所有記錄的記錄集在comodel_name
,例如字段inverse_name
就等於當前記錄。
Parameters:
comodel_name – name of the target model (string)
目標模型的名稱(字符串)
inverse_name – name of the inverse Many2one field incomodel_name
(string)
在comodel_name
相反的Many2one字段的名稱(string)
domain – an optional domain to set on candidate values on the client side (domain or string) 在客戶端上設置候選值的可選域(域或字符串)
context – an optional context to use on the client side when handling that field (dictionary) 在處理該字段時在客戶端使用的可選上下文(dictionary)
auto_join – whether JOINs are generated upon search through that field (boolean, by default False) 是否JOINs是通過字段搜索產生的(布爾值,默認為False)
limit – optional limit to use upon read (integer) 閱讀時可選擇的限制(integer)
除了相關字段或字段擴展名之外,屬性comodel_name
和inverse_name
都是必需的。
Many2many
class odoo.fields.Many2many(comodel_name=<object object>, relation=<object object>, column1=<object object>, column2=<object object>, string=<object object>, **kwargs)
基類:odoo.fields._RelationalMulti
Many2many字段;這樣一個字段的值就是記錄集。
Parameters:
comodel_name – name of the target model (string) 目標模型名稱(string)
除了相關字段或字段擴展的情況外,屬性comodel_name
是強制性的。
Parameters
relation – optional name of the table that stores the relation in the database (string) 在數據庫中儲存關系的表的可選名稱(string)
column1 – optional name of the column referring to “these” records in the table relation (string) 列的可選名稱,指的是表關系中的“這些”記錄
column2 – optional name of the column referring to “those” records in the table relation (string) 列的可選名稱,指的是表關系中的“那些”記錄
屬性ralation
、column1
和column2
是可選的。如果沒有給出,名稱將自動從模型名稱中生成,提供的model_name
和comodel_name
是不同的!
Parameters
domain – an optional domain to set on candidate values on the client side (domain or string) 在客戶端上設置候選值的可選域(domain或者字符串)
context – an optional context to use on the client side when handling that field (dictionary) 在處理該字段時在客戶端使用的可選context
limit – optional limit to use upon read (integer) 閱讀時可選擇的限制(integer)
project_ids = fields.Many2many('project.project', 'project_task_type_rel', 'type_id', 'project_id', string='Projects',
default=_get_default_project_ids)
project.project 對應的關聯表
project_task_type_rel 自定義多對多關系表名字
type_id 自定義多對多關系表對方的表
project_id 自定義對方關系表本方字段
Reference
class odoo.fields.Reference(selection=<object object>, string=<object object>, **kwargs)
基類: odoo.fields.Selection
繼承和擴展(Inheritance and extension)
Odoo提供了三種不同的機制來以模塊化的方式擴展模型:
- 從現有的模型中創建一個新模型,向副本添加新信息,但保留原始模塊(第一種Classical inheritance)
- 擴展其他模塊中定義的模型,取代以前的版本(第二種擴展繼承(Extension))
- 把模型的一些字段委托給它包含的記錄(第三種委托繼承(Delegation))
經典繼承(Classical inheritance)
當使用inherit
和_name
屬性時,Odoo使用現有的模型(通過繼承提供的)作為基礎創建一個新模型。這個新模型從它的基礎上獲得所有的字段、方法和元信息(defaults & al)。
class Inheritance0(models.Model):
_name = 'inheritance.0'
name = fields.Char()
def call(self):
return self.check("model 0")
def check(self, s):
return "This is {} record {}".format(s, self.name)
class Inheritance1(models.Model):
_name = 'inheritance.1'
_inherit = 'inheritance.0'
def call(self):
return self.check("model 1")
然后使用它們
a = env['inheritance.0'].create({'name': 'A'})
b = env['inheritance.1'].create({'name': 'B'})
a.call()
b.call()
會產生:
"This is model 0 record A"
"This is model 1 record B"
第二種模型繼承了第一種模型的check
方法及其name
字段,但是重寫了call
方法,就像使用標准Python繼承一樣。
擴展繼承(Extension)
當使用inherit
而忽略_name
時,新模型將替換現有的模型,本質上是將其擴展到適當的位置。這對於向現有模型(在其他模塊中創建)添加新的字段或方法是很有用的,或者對它們進行定制或重新配置(例如,更改它們的默認排序順序):
class Extension0(models.Model):
_name = 'extension.0'
name = fields.Char(default="A")
class Extension1(models.Model):
_inherit = 'extension.0'
description = fields.Char(default="Extended")
env = self.env
{'name': "A", 'description': "Extended"}
它還會產生各種自動字段(automatic fields),除非它們已經被禁用了
委托繼承(Delegation)
第三種繼承機制提供了更多的靈活性(可以在運行時進行修改),但更少的權力:使用inherits
模型將模型中查找不能找到的任何字段的委托給“children(子)”模型。該委托繼承是通過在父模型上自動建立的Reference
字段來執行的:
class Child0(models.Model):
_name = 'delegation.child0'
field_0 = fields.Integer()
class Child1(models.Model):
_name = 'delegation.child1'
field_1 = fields.Integer()
class Delegating(models.Model):
_name = 'delegation.parent'
_inherits = {
'delegation.child0': 'child0_id',
'delegation.child1': 'child1_id',
}
child0_id = fields.Many2one('delegation.child0', required=True, ondelete='cascade')
child1_id = fields.Many2one('delegation.child1', required=True, ondelete='cascade')
record = env['delegation.parent'].create({
'child0_id': env['delegation.child0'].create({'field_0': 0}).id,
'child1_id': env['delegation.child1'].create({'field_1': 1}).id,
})
record.field_0
record.field_1
將產生如下結果
0
1
也可以直接寫在委托的字段:
record.write({'field_1': 4})
域(Domains)
域是標准的列表,每個標准是(field_name
、operator
、value
)的三重(即列表或元組):
field_name (str)
當前模型的一個字段名,或者是通過使用點符號的Many2one
的關系遍歷。“street
”或“partner_id.country
”
operator (str)
一個操作符用來比較字段名和值. 存在的操作符:
=
equals to
!=
not equals to
>
greater than
>=
greater than or equal to
<
less than
<=
less than or equal to
=?
unset or equals to (returns true if value is either None or False, otherwise behaves like =)
=like
matches field_name against the value pattern. An underscore _ in the pattern stands for (matches) any single character; a percent sign % matches any string of zero or more characters.
like
matches field_name against the %value% pattern. Similar to =like but wraps value with ‘%’ before matching
not like
doesn’t match against the %value% pattern
ilike
case insensitive like
not ilike
case insensitive not like
=ilike
case insensitive =like
in
is equal to any of the items from value, value should be a list of items
not in
is unequal to all of the items from value
child_of
is a child (descendant) of a value record.
Takes the semantics of the model into account (i.e following the relationship field named by _parent_name).
value
variable type, must be comparable (through operator) to the named field
Domain criteria can be combined using logical operators in prefix form:
'&'
logical AND, default operation to combine criteria following one another. Arity 2 (uses the next 2 criteria or combinations).
'|'
logical OR, arity 2.
'!'
logical NOT, arity 1.