前言

在odoo的ORM创建数据字段的过程中,我们会经常需要定义一些字段用来计算某一些字段只和或其他计算结果。

今天介绍一个很好用的方法compute计算属性,这个方法其实是属于写在odoo fields中的属性,但是因为非常常用,还涉及ORM中的方法所以今天就单独列出来详细讲解它的用法。

如何使用odoo compute属性实现自动计算字段

我们看下面的案例。

class FandxProduct(models.Model):
_name = "fandx.product" name = fields.Char("产品名称")
nums = fields.Integer("数量")
unit_price = fields.Float("产品单位价格")

现在有个需求,这是一个产品表,我们需要计算他的每一个产品的总价格(产品单位价格*数量),这时候就要用到我们的主角compute属性,下面看案例。

class FandxProduct(models.Model):
_name = "fandx.product" name = fields.Char("产品名称")
nums = fields.Integer("数量")
unit_price = fields.Float("产品单位价格")
# 使用_compute_all_price
all_price = fields.Float("产品总价格", compute="_compute_all_price") def _compute_all_price(self):
# self取值默认是multi,所以需要循环拿到每一个record的值
for record in self:
# 计算每一个record的all_price的值进行赋值
record.all_price = record.unit_price * record.nums

在字段中定义属性compute并指向计算方法,在数据创建的时候会自动计算这个字段的数据。

这样我们在XML中使用all_price就可以获取到产品的总价格,但是这里还有一个问题。

数据库中是没有进行持久存储的,那么数据数据量一大,每次渲染页面都要进行计算,这样是非常消耗服务器性能的,所以我们就要将计算的字段给存储起来。

如何存储odoo compute计算字段的值

方法很简单,只需要在定义的field中加上store字段,这样就会把计算到的结果给存储到数据库中。

class FandxProduct(models.Model):
_name = "fandx.product" name = fields.Char("产品名称")
nums = fields.Integer("数量")
unit_price = fields.Float("产品单位价格")
# 使用_compute_all_price
# 在字段中加上store = True实现数据的持久化
all_price = fields.Float("产品总价格", compute="_compute_all_price", store=True) def _compute_all_price(self):
# self取值默认是multi,所以需要循环拿到每一个record的值
for record in self:
# 计算每一个record的all_price的值进行赋值
record.all_price = record.unit_price * record.nums

这样我们在数据库中就有了all_price的字段来记录产品总价格。

但是现在又出现一个问题,计算字段是计算出了我们的结果,但是如果nums改变,或者unit_price改变了,计算字段并不会改变怎么办!

compute配合使用depends监听数据变化

class FandxProduct(models.Model):
_name = "fandx.product" name = fields.Char("产品名称")
nums = fields.Integer("数量")
unit_price = fields.Float("产品单位价格")
# 使用_compute_all_price
# 在字段中加上store = True实现数据的持久化
all_price = fields.Float("产品总价格", compute="_compute_all_price", store=True) # 将nums、unit_price字段进行监听,在数据变动的时候再次执行compute指向的方法进行重新赋值计算。
@api.depends('nums', 'unit_price')
def _compute_all_price(self):
# self取值默认是multi,所以需要循环拿到每一个record的值
for record in self:
# 计算每一个record的all_price的值进行赋值
record.all_price = record.unit_price * record.nums

到这里就基本实现了compute的所有经常使用的方法,下面一般会配合compute一起使用的属性inverse

odoo中逆向计算inverse属性使用详解

上面讲解了compute方法是用来计算对应的数据字段的。

inverse方法其实就是compute的逆向方法,默认情况下xml中对应的compute计算字段是readonly的。

当我们加上inverse逆向计算的时候,那么就可以在XML中输入对应的值,然后系统会走inverse对应的方法。

class FandxProduct(models.Model):
_name = "fandx.product" name = fields.Char("产品名称")
nums = fields.Integer("数量")
unit_price = fields.Float("产品单位价格")
# 使用_compute_all_price
# 在字段中加上store = True实现数据的持久化
all_price = fields.Float("产品总价格", compute="_compute_all_price", inverse='_set_unit_price', store=True) # 将nums、unit_price字段进行监听,在数据变动的时候再次执行compute指向的方法进行重新赋值计算。
@api.depends('nums', 'unit_price')
def _compute_all_price(self):
# self取值默认是multi,所以需要循环拿到每一个record的值
for record in self:
# 计算每一个record的all_price的值进行赋值
record.all_price = record.unit_price * record.nums def _set_unit_price(self):
for record in self:
if not all([record.nums, record.all_price]):
continue # 当我们手动修改all_price的值的时候,我们就可以逆向去计算出unit_price的值,进行重新赋值。
record.unit_price = record.all_price / record.nums

总结

  1. odoo的compute可以实现我们对数据字段自动计算的需求。
  2. fields中加入store属性可以实现数据的持久化存储。
  3. compute计算字段在持久化存储之后不会在自动计算,需要我们配合depends来监听指定计算字段在数据改动的时候重新计算数据字段。
  4. inverse方法可以帮助我们解决compute计算字段readonly的问题,并在输入对应的字段进行逆向计算之前的字段。
  5. compute字段默认是store为False的所有search是无效的,还可以指定search的方式实现搜索。这里就不去细讲了,很简单也不常用。
  6. 还有compute_sudo属性可以设置字段在使用的时候是否以超级管理员的方式来进行计算,这里store=True的时候默认为True,否则默认为False,了解一下就可以了。
  7. 如果有问题可以在下方留言。

如何使用odoo的compute方法,自动计算odoo字段的更多相关文章

  1. odoo开发基础--模型之基本字段类型

    定义模型的时候,和python的其他框架类似,可以对比Django,同样是一个模型即:一个class对应生成数据库中的一张表, 只是odoo的继承机制比较复杂一点,在日常的开发中,定义模型的时候, 基 ...

  2. C#中DataTable中的Compute方法使用收集

    原文: C#中DataTable中的Compute方法使用收集 Compute函数的参数就两个:Expression,和Filter. Expresstion是计算表达式,关于Expression的详 ...

  3. [datatable]借助DataTable的Compute方法

    借助DataTable的Compute方法,DataTable中数据不用事先排好序. 下面代码中的dt是跟前面的是一样的 DataTable dtName = dt.DefaultView.ToTab ...

  4. C# DataTable Compute方法的使用

    在开发中需要对DataTable的数据进行处理,比如累加,求最大最小及平均值等,以前都采用手工对DataTable进行循环并计算的方式,现在发现DataTable的Compute方法可以轻松实现这些功 ...

  5. 给 odoo 的 bom 明细加上位置字段

    给 odoo 的 bom 明细加上位置字段 odoo 的 BOM 明细没有位置字段,这可无法用于电子生产中. 摸索了几天,找了一些教程,最终实现了. 在模型中找到 mrp_bom_line 增加自定义 ...

  6. c# 基于DataTable的Compute方法的扩展

    DataTable.Compute(String, String) 方法 定义 命名空间:System.Data 程序集:System.Data.dll, netstandard.dll, Syste ...

  7. 转载 C#中DataTable中的Compute方法使用收集

    原文: C#中DataTable中的Compute方法使用收集 Compute函数的参数就两个:Expression,和Filter. Expresstion是计算表达式,关于Expression的详 ...

  8. LINQ找出重复和不重复的元素及linq OrderBy 方法 两个字段同时排序有关问题

    //重复元素:3,4,5 //不重复元素:1,8,9 , , , , , , , , , , }; //不重复元素 var unique = arr.GroupBy(i => i) .Where ...

  9. 【转载】Sqlserver使用IsNull方法对空字段进行赋值操作

    在Sqlserver的SQL语句查询过程或者编写存储过程以及自定义函数过程中,有时候字段的值为空,如果为空的字段需要赋值一个默认值,可以使用Sqlserver内置系统函数IsNull来给定一个默认值, ...

随机推荐

  1. 10: java数据结构和算法: 构建哈夫曼树, 获取哈夫曼编码, 使用哈夫曼编码原理对文件压缩和解压

    最终结果哈夫曼树,如图所示: 直接上代码: public class HuffmanCode { public static void main(String[] args) { //获取哈夫曼树并显 ...

  2. springMVC异常处理(自定义异常)HandlerExceptionResolver

    注:本篇的异常主要指的是controller.service和dao层中执行方法抛出的异常. 一.为什么要处理异常? 因为如果我们不处理异常,异常信息就会直接抛出给浏览器,于是浏览器页面就直接显示异常 ...

  3. UF_UI 界面相关

    Open C   uc1600uc1601uc1603  uc1605uc1607uc1608uc1609uc1613  获取用户输入的字符串uc1615uc1616uc1617uc1618uc163 ...

  4. 【NX二次开发】获取对象边界包容盒的三个函数UF_MODL_ask_bounding_box

    今天看到胡工对bounding_box的分享,我也来测试一番(原帖地址:https://www.ugapi.com/thread-10287.html) 获取对象的边界盒子的三个函数: 1 UF_MO ...

  5. 基于 Spring Security 的前后端分离的权限控制系统

    话不多说,入正题.一个简单的权限控制系统需要考虑的问题如下: 权限如何加载 权限匹配规则 登录 1.  引入maven依赖 1 <?xml version="1.0" enc ...

  6. 详解Apache Dubbo的SPI实现机制

    一.SPI SPI全称为Service Provider Interface,对应中文为服务发现机制.SPI类似一种可插拔机制,首先需要定义一个接口或一个约定,然后不同的场景可以对其进行实现,调用方在 ...

  7. 代码生成器:IDEA 强大的 Live Templates

    前言 Java 开发过程经常需要编写有固定格式的代码,例如说声明一个私有变量,logger或者bean等等.对于这种小范围的代码生成,我们可以利用 IDEA 提供的 Live Templates功能. ...

  8. Linux操作系统(一)

    计算机本身就是一堆硬件,这些硬件中最核心的就是CPU(运算器,控制器) 和存储器设备. 为了能够实现计算机获取数据,数据的输入输出等等需要输入设备和输出设备. 计算机体系内部:主要是通过桥接接入当前系 ...

  9. Golang学习(用代码来学习) - 第五篇

    /** 并发控制:context的学习 */ func context_test() { PrintStartSeperator("context_test") ctx, canc ...

  10. 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...