Odoo12 ORM API ☞ Creating Models

Creating Models(创建模型)

模型字段定义为模型本身的属性:

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

    field1 = fields.Char()

Warning!
这意味着您无法定义具有相同名称的字段和方法,它们会发生冲突

默认情况下,字段的标签(用户可见名称)是字段名称的大写版本,可以使用 string 参数修改:

field2 = fields.Integer(string="an other field")

关于有关各种字段类型和参数,请参阅 Fields
默认值被定义为字段上的参数,值为:

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
  • 依赖关系中模型字段可以通过的方式获取:
@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’***属性。该属性值为一个方法,方法返回值为domain:
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***属性来设置计算字段的值。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')

@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

计算字段的特例是相关(代理)字段,它提供当前记录中模型字段的值。它们是通过设置相关参数来定义的,就像它们可以存储的常规计算字段一样:

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

onchange: updating UI on the fly(动态更新UI)

当用户更改表单中的字段值时(但尚未保存表单),根据该值自动更新其他字段会很有用。例如:更改税额或添加新发票行时更新最终总计。

  • 计算字段会自动检查并重新计算,不需要 onchange
  • 对于非计算字段,onchange() 装饰器用于更新字段值:
@api.onchange('field1', 'field2')    # 当这些字段被更改,会调用方法
def check_change(self):
    if self.field1 < self.field2:
        self.field3 = True

这些修改完成时将更新结果返回到客户端程序并展现给用户。

  • 客户端自动调用计算字段和new-API onchanges,而无需在视图中添加它们
  • 如果不想某一字段触发onchange,可以通过向视图中添加 on_change="0" 来实现。
<field name="name" **on_change**="0"/>

当用户编辑字段时,即使有功能字段或显式onchange取决于该字段,也不会触发任何接口更新。

onchange方法对这些记录上的虚拟记录赋值工作没有写入数据库,只是用来知道要将哪个值返回客户端。

Warning!
one2many或many2many字段不可能通过onchange修改自身。这是webclient限制

Low-level SQL(简单SQL)

环境中的***cr***属性是当前数据库事务的游标,允许直接执行SQL。当使用ORM难以表达的查询(例如复杂连接),或者出于性能原因就可以直接执行SQL来实现。

self.env.cr.execute("some_sql", param1, param2, param3)

由于模型使用相同的游标,并且Environment包含各种缓存,因此在使用原生SQL更改数据库时,必须无效这些缓存,否则模型的进一步操作可能会有问题。就需要使用SQL语句中的CREATE、UPDATE or DELETE而不是SELECT(用于读取数据库记录)来清除缓存。

可以使用 BaseModel 对象的 invalidate_cache() 方法执行清除缓存。

猜你喜欢

转载自blog.csdn.net/sinat_23931991/article/details/84989906