Odoo 之业务逻辑 - 业务流程的支持
一·ORM 方法装饰器
单例记录方法:@api.one
# 1. @api.one装饰的方法内,self 一定是单例
# 2. for 循环遍历,它调用装饰方法,一次一条记录,然后返回一个结果列表
# 3. self.ensure_one() 来确保操作的是单条记录。
类静态方法:@api.model
# 1. 需要在类级别而不是具体记录上操作
# 2. self 应作为模型的引用 ,无需包含实际记录
监听方法: @api.onchange
# 1. onchange由用户界面表单视图触发,当用户编辑指定字段值时,立即执行一段业务逻辑
# 2. 可用于验证和向用户提示消息和修改表单中其他字段
# 3. 监控装饰器内的字段,一旦发生变化,则触发当前行数
# 4. 在页面中,on_change=”0″ 可关闭on change行为
@api.onchange('member_id')
def onchange_member_id(self):
pass
计算字段函数: @api.depends(fld1,…)
### 来识别(重新)计算应触发什么样的修改。必须设置在计算字段值上,否则会报错
@api.depends('member_id')
def _compute_member_id(self):
pass
约束字段: @api.constrains()
### 用于模型验证,不向数据库写入修改,如检查失败,则抛出异常。
@api.constrains('member_id')
def _constrains_member_id(self):
pass
二·ORM 内置方法
写入模型数据的方法
# 1. values参数是一个字典,映射要写入的字段名和值
# 2. reate()方法使用@api.model装饰器外。
<Model>.create(values)在模型上创建新记录,它返回所创建记录。
<Recordset>.write(values) 更新记录集中的字段值,它不返回值。
<Recordset>.unlink()从数据库中删除记录,它不返回值。
# 3. 在执行super().create(vals)命令之前可以对值字典进行修改
# 4. 一般会尽量在super().write(vals)之前修改写入的值
# 避免递归循环的一个技巧是在上下文中添加一个标记
if not self.env.context.get('_library_checkout_writing'):
self.with_context(_library_checkout_writing=True).write(some_values)
数据导入、导出方法
# load([fields], [data]) 用于导入从 CSV 文件中获取的数据
# 第一个参数是导入的字段列表 与CSV 的第一行对应
# 第二个参数是记录列表 每条记录是一个待解析和导入的字符串列表,与 CSV 数据中的行和列直接对应
# export_data([fields], raw_data=False)用于网页客户端导出函数
# 返回一个字典,带有包含数据(一个行列表)的数据键
三· 消息和活动(activity)功能 (内容有误差.不能提供完整信息)
# Odoo 自带全局的消息和活动规划功能,由 Discuss 应用提供,技术名称为 mail
# mail模块提供包含mail.thread抽象类.在任意模型中添加消息功能都变得很简单
### 模型就会添加三个新字段
message_follower_ids # 存储 followers 和相应的通知首选项
message_ids # 列出所有包含关联活动规划的关联messages.activity_id
消息子类型
### 默认有如下三种消息子类型
Discussions # 带有mail.mt_comment XML ID,用于创建带有Send message链接的消息,默认会发送通知。
Activities # 带有mail.mt_activities XML ID,用于创建带有Schedule activity链接的消息,默认不会发送通知。
Note # 带有mail.mt_note XML ID,用于创建带有Log note链接的消息,默认不会发送通知。
发送消息
添加 follower
message_subscribe(partner_ids=)
四· 创建向导wizard
向导模型
#### 分析:
# 1.向导对于用户显示,也是一个表单视图,通常是一个对话窗口
# 2.向导支持继承的模型是 models.TransientMode ,而不是 models.Model.
# 3.这类向导模型也会存储在数据库种,数据仅在向导完成前有用.定时运行job定期清楚向导种的数据
### 步骤
# 1.创建 wizard/子目录 ,在library_checkout/__init__.py文件并导入
from . import models
from . import wizard
# 2. wizard/__init__.py中添加py文件
from . import checkout_mass_message
# 3. 创建实际的wizard/checkout_mass_message.py
from odoo import api, exceptions, fields, models
class CheckoutMassMessage(models.TransientModel):
_name = 'library.checkout.massmessage'
_description = 'Send Message to Borrowers'
checkout_ids = fields.Many2many(
'library.checkout',
string='Checkouts')
message_subject = fields.Char()
message_body = fields.Html()
#注意:
# 1.普通模型中的one-to-many关联不能在临时模型中使用. 需要在普通模型中添加与临时模型的方向many-to-one关联. 普通记录的已有引用会阻止对老的临时记录的清除
# 2.Many-to-many关联存储在独立的表中,会在关联任意一方被删除时自动删除表中对应行。
# 3. 临时模型无需安全规则 ,因为它们是用于辅助执行的一次性记录. 不需要添加权限控制文件
向导表单
# 与普通模型相同,只有两个特定的元素
# 1. 可使用<footer>元素来替换操作按钮
# 2. special=”cancel”按钮用于中断向导,不执行任何操作
<!-- wizard/checkout_mass_message_wizard.xml文件的内容如下: -->
<?xml version="1.0"?>
<odoo>
<record id="view_form_checkout_message" model="ir.ui.view">
<field name="name">Library Checkout Mass Message Wizard</field>
<field name="model">library.checkout.massmessage</field>
<field name="arch" type="xml">
<form>
<group>
<field name="message_subject" />
<field name="message_body" />
<field name="checkout_ids" />
</group>
<footer>
<button type="object"
name="button_send"
string="Send Message" />
<button special="cancel"
string="Cancel"
class="btn-secondary" />
</footer>
</form>
</field>
</record>
<act_window id="action_checkout_message"
name="Send Messages"
src_model="library.checkout"
res_model="library.checkout.massmessage"
view_type="form"
view_mode="form"
target="new"
multi="True"
/>
</odoo>
# Odoo 视图向上下文字典添加一些元素,可在点击操作或跳到其它视图时使用。它们分别是:
- active_model:带有视图模型的技术名
- active_id:带有表单活跃记录或表中第一条记录的 ID
- active_ids:带有一个列表中活跃记录的列表(如果是表单则只有一个元素)
- active_domain:如果在表单视图中触发了该操作
# wizard/checkout_mass_message.py
@api.model
def default_get(self, field_names):
defaults = super().default_get(field_names)
checkout_ids = self.env.context.get('active_ids')
defaults['checkout_ids'] = checkout_ids
return defaults
向导业务逻辑
# wizard/checkout_mass_message.py
def button_send(self):
self.ensure_one()
for checkout in self.checkout_ids:
checkout.message_post(
body=self.message_body,
subject=self.message_subject,
subtype='mail.mt_comment',
)
return True