Alan Hou的个人博客

Odoo高级服务端开发技巧

这是Odoo系列文章的第九篇,完整目录请见最好用的免费ERP系统Odoo 11开发指南

以下开发均假设读者已完成第八篇的代码,并且所有代码更新后均需自行更新方会在客户端看到变化。如未阅读该篇,请参考代码:Chapter 8

本文主要内容有

修改运行指定动作用户

在书写业务逻辑代码时,常会需要在不同权限上下文中操作动作,比如使用管理员权限绕过权限检查。下面我们来看一下普通用户如何使用 sudo()来修改公司电话号码。默认仅 Administration/Access Rights 用户组的用户可修改 res.company 记录。

注意:使用 sudo()时的操作是不可追踪的,所以使用 update_phone_number 后查看到的最后修改人仍是管理员,OCA的 base_suspend_security 可用于突破这一限制。

扩展知识

使用 sudo()不加参用户的上下文会变成 Odoo 超级管理员,该用户不受任何权限控制列表(acl)和记录集的权限规则限制。默认该用户有一个 company_id 字段设置为实例的主公司(ID 为1),这对于多公司的场景会存在问题:

小贴士:使用 sudo()时,反复确认调用 search()时不依赖标准记录集过滤结果,并确保在执行 create()时不使用当前用户字段 如 company_id 所计算的默认值。

使用 sudo()也会创建一个新的 Environment 实例,该环境初始带有一个空的记录集缓存 ,它与 self.env 的缓存是独立开来的。这可能会导致伪造数据查询,请避免在循环内创建新环境,并且越靠外层越好。

以变更的上下文调用方法

上下文是记录集环境的一部分,用于传递时区、用户界面语言、及动作中指定的上下文参数等信息。标准插件中的很多方法都使用上文来根据这些值来调整行为,有时需要变更记录集上下文来从方法调用获取预期结果或从可计算字段获取预期值。以下讨论在给定的 stock.location 中读取 product.product 的仓储级别。

以下会使用到 stock 和 product 两个 addon

以上 self.with_context()传递了一些参数,它返回一个新的带有键值的 self 版本(product.product 记录集),两个键分别为:

扩展知识

也可为 self.with_context()传入字典,此时字典会覆盖原有环境成为新的上下文,上述对应代码可修改为

同样的使用 with_context()会创建一个新的 Environment 实例,该环境初始带有一个空的记录集缓存 ,它与 self.env 的缓存是独立开来的。这可能会导致伪造数据查询,请避免在循环内创建新环境,并且越靠外层越好。

执行原生 SQL 语句

大多数情况下,可以使用 search()方法执行操作,但有时这并不够,比如使用域的句法无法达到要求,或者一些查询需要多次调用 search()而导致效率低下。

以下我们将使用原生 SQL 查询来读取按国家分组的 res.partner 记录。

扩展知识

self.env.cr 是 包裹psycopg2游标(cursor)的装饰器,以下是常用的一些方法:

处理原生 SQL 查询时应注意:

为用户编写向导

我们在第五篇中曾介绍过 models.TransientModel 基类,该类与很多常规类相似,不同之处在于会在数据库中定期清理,所以才会被称为临时模型。一般用于创建向导或对话框,由用户在界面中填写然后再向数据库的持久记录操作。

下面我们向之前的模块添加记录借书的向导

然后在 xml 添加对应的菜单设置即可。TransientModel 的不同之处在于

xml 文件中 button 类型设置为 object 表明在点击按钮时会调用name 属性所赋值的方法,操作中的target=’new’会在当前表单之上显示一个对话框。

扩展知识

以下可用于增强向导的功能:

使用上下文计算默认值

以上的向导要求用户填写姓名,web 客户端的特性可以让用户少打一些字,在操作执行时,上下文可以更新一些值给向导使用

Key Value
active_model 与操作相关的模型,通常是屏幕上显示的模型
active_id 表明单条记录处于活跃状态,提供出该记录的 ID
active_ids 在选择多条记录时,则会是一个 ID 列表(树状视图中选择多条),在表单视图中得到[active_id]
active_domain 向导所操作的额外的域

这些值可用于计算模型的默认值,甚至直接通过按钮给方法调用。假如在 library.member 模型的表单视图中有一个按钮启动向导,向导创建的上下文中会包含{‘active_model’:’library.member’, ‘active_id’:<member id>},这时可以使用如下方法定义 member_id 字段来计算默认值

向导和代码复用

在方法中我们可以将 for wizard 设为自循环,假设 len(self)为1,可以在方法最前面调用 self.ensure_one()

推荐使用这段代码,因为这样可以通过为向导创建记录在其它部分的代码中复用这个向导,放到一个单独的记录集中然后调用记录集中的 record_loans()。确实在此处代码有些琐碎并且无需通过所有的不同成员借用某些书的循环。但在 Odoo 实例中,有些操作更为复杂,通常有向导来做“对的事”会比较好。使用这类向导时,确保查看上下文中任何使用 active_model/active_id/active_ids 键的源代三,这时应传入自定义的上下文。

重定向用户

 

正在更新中…

退出移动版