环境
odoo-14.0.post20221212.tar
context用法总结
获取上下文
>>> self.env.context # 返回字典数据,等价于 self._context {'lang': 'en_US', 'tz': 'Europe/Brussels'} >>> self._context {'lang': 'en_US', 'tz': 'Europe/Brussels'} >>> recordSet.env.context # 注意,上下文是和记录集绑定的,上述的self也代表记录集
设置上下文
Model.with_context([context][, **overrides])
-> records[源代码]
返回附加到扩展上下文的此记录集的新版本。
扩展上下文是提供的合并了overrides
的context
,或者是合并了overrides
当前context
# 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}
需要注意的是,上下文是和记录集绑定的,修改后的上下文并不会在其它记录集中共享
应用场景示例
用于action,为关联视图添加默认搜索、过滤条件
视图定义
为设置action打开的tree列表视图,添加默认搜索,搜索条件为 state
字段值等于True
<?xml version="1.0"?> <odoo> <record id="link_estate_property_action" model="ir.actions.act_window"> <field name="name">Properties</field> <field name="res_model">estate.property</field> <field name="view_mode">tree,form</field> <field name="context">{'search_default_state': True}</field> </record> <record id="estate_property_search_view" model="ir.ui.view"> <field name="name">estate.property.search</field> <field name="model">estate.property</field> <field name="arch" type="xml"> <search> <!-- 搜索 --> <field name="name" string="Title" /> <separator/> <!-- 筛选 --> <filter string="Available" name="state" domain="['|',('state', '=', 'New'),('state', '=', 'Offer Received')]"></filter> </search> </field> </record> <!--此处代码略...--> </odoo>
说明:
<field name="context">{'search_default_fieldName': content}</field>
search_default_fieldName
,其中fieldName
表示过滤器名称,即搜索视图中定义的<field>
、<filter>
元素的name
属性值
content
如果fieldName
为搜索字段<field>
的name
属性值,那么content
表示需要搜索的内容,输入内容是字符串,则需要添加引号,形如'test'
;如果fieldName
为搜索过滤器<filter>
的name
属性值,那么content
表示布尔值,该值为真,则表示默认开启name
所代表的过滤器,否则不开启。
用于搜索视图,添加分组查询条件
视图设计
<?xml version="1.0"?> <odoo> <!--此处代码略...--> <record id="estate_property_search_view" model="ir.ui.view"> <field name="name">estate.property.search</field> <field name="model">estate.property</field> <field name="arch" type="xml"> <search> <!-- 分组 --> <group expand="1" string="Group By"> <filter string="朝向" name="garden_orientation" context="{'group_by':'garden_orientation'}"/> </group> </search> </field> </record> <!--此处代码略...--> </odoo>
说明:'group_by': '分组字段名称'
用于视图对象按钮,传递数据给模型方法
模型设计
#!/usr/bin/env python # -*- coding:utf-8 -*- from odoo import models, fields, api class EstatePropertyType(models.Model): _name = 'estate.property.type' _description = 'estate property type' name = fields.Char(string='name', required=True, help='help text') property_ids = fields.One2many('estate.property', 'property_type_id') offer_ids = fields.One2many('estate.property.offer', 'property_type_id') offer_count = fields.Integer(compute='_compute_offer_count') @api.depends('offer_ids.price') def _compute_offer_count(self): for record in self: record.offer_count = len(record.mapped('offer_ids.price')) @api.model def action_confirm(self, *args): print(self, self.env.context, args) # ... do something else
视图设计
<?xml version="1.0"?> <odoo> <!--此处代码略...--> <record id="estate_property_type_view_form" model="ir.ui.view"> <field name="name">estate.property.type.form</field> <field name="model">estate.property.type</field> <field name="arch" type="xml"> <form string="Property Type"> <sheet> <!--此处代码略...--> <field name="offer_count"> <field name="property_ids"> <tree string="Properties"> <field name="name"/> <field name="expected_price" string="Expected Price"/> <field name="state" string="Status"/> </tree> </field> <footer> <button name="action_confirm" type="object" context="{'currentRecordID': active_id, 'offer_count':offer_count, 'property_ids': property_ids}" string="确认" class="oe_highlight"/> </footer> </sheet> </form> </field> </record> </odoo>
说明:context
属性值中的字典的键值如果为模型中定义的字段名称,则该字段名称必须以<field>
元素的形式,出现在模型对应的视图(即不能是内联视图,比如内联Tree列表)中,否则会出现类似错误提示:
Field offer_count used in context.offerCount ({'offerCount': offer_count}) must be present in view but is missing.
点击界面按钮后,服务端打印日志如下
estate.property.type() {'lang': 'en_US', 'tz': 'Europe/Brussels', 'uid': 2, 'allowed_company_ids': [1], 'params': {'action': 165, 'cids': 1, 'id': 1, 'menu_id': 70, 'model': 'estate.property.type', 'view_type': 'form'}, 'currentRecordID': 1, 'offer_count': 4, 'property_ids': [[4, 49, False], [4, 48, False]]} ([1],)
说明:args
从日志来看,args
接收了当前记录ID
注意:
- 如果将
def action_confirm(self, *args)
改成def action_confirm(self, arg)
,服务端控制台会收到类似如下告警(虽然点击按钮后,服务端不会抛异常):
2023-02-06 01:28:53,848 28188 WARNING odoo odoo.addons.base.models.ir_ui_view: action_confirm on demo.wizard has parameters and cannot be called from a button
- 如果将
def action_confirm(self, *args)
改成def action_confirm(self)
,则点击页面确认按钮时,服务端会报错误,如下:
TypeError: action_confirm2() takes 1 positional argument but 2 were given
用于视图动作按钮,传递数据给动作关联的视图
视图设计
<?xml version="1.0"?> <odoo> <!--此处代码略...--> <record id="estate_property_view_form" model="ir.ui.view"> <field name="name">estate.property.form</field> <field name="model">estate.property</field> <field name="arch" type="xml"> <form string="estate property form"> <header> <button name="%(action_demo_wizard)d" type="action" string="选取offers" context="{'is_force':True}" class="oe_highlight"/> <!--此处代码略...--> </sheet> </form> </field> </record> </odoo>
传递数据给视图按钮
action_demo_wizard
action关联视图设计
<?xml version="1.0" encoding="UTF-8"?> <odoo> <data> <!--此处代码略...--> <record id="demo_wizard_view_form" model="ir.ui.view"> <field name="name">demo.wizard.form</field> <field name="model">demo.wizard</field> <field name="arch" type="xml"> <form> <!--此处代码略...--> <footer> <button name="action_confirm" context="{'is_force':context.get('is_force')}" string="确认" class="oe_highlight"/> <button string="关闭" class="oe_link" special="cancel"/> </footer> </form> </field> </record> <!-- 通过动作菜单触发 --> <record id="action_demo_wizard" model="ir.actions.act_window"> <field name="name">选取offers</field> <field name="res_model">demo.wizard</field> <field name="type">ir.actions.act_window</field> <field name="view_mode">form</field> <field name="target">new</field> <field name="binding_model_id" ref="estate.model_estate_property"/> <field name="binding_view_types">form</field> </record> </data> </odoo>
传递数据给视图关系字段
<?xml version="1.0" encoding="UTF-8"?> <odoo> <data> <!--此处代码略...--> <record id="demo_wizard_view_form" model="ir.ui.view"> <field name="name">demo.wizard.form</field> <field name="model">demo.wizard</field> <field name="arch" type="xml"> <form> <field name="offer_ids" context="{'is_force':context.get('is_force')}" > <tree> <!--此处代码略...--> </tree> </field> <!--此处代码略...--> </form> </field> </record> <!-- 通过动作菜单触发 --> <record id="action_demo_wizard" model="ir.actions.act_window"> <field name="name">选取offers</field> <field name="res_model">demo.wizard</field> <field name="type">ir.actions.act_window</field> <field name="view_mode">form</field> <field name="target">new</field> <field name="binding_model_id" ref="estate.model_estate_property"/> <field name="binding_view_types">form</field> </record> </data> </odoo>
用于视图关系字段,传递数据给模型方法
模型设计
#!/usr/bin/env python # -*- coding: utf-8 -*- from odoo import models, fields class EstateProperty(models.Model): _name = 'estate.property' _description = 'estate property table' name = fields.Char(required=True) property_type_id = fields.Many2one("estate.property.type", string="PropertyType", options="{'no_create_edit': True}") offer_ids = fields.One2many("estate.property.offer", "property_id", string="PropertyOffer") # ...此处代码略 # 重写父类read方法 def read(self, fields=None, load='_classic_read'): print(self.env.context) property_type_id = self.env.context.get('propertyTypeId') if property_type_id: print('do something you want') return super(EstateProperty, self).read(fields, load)
视图设计
<?xml version="1.0"?> <odoo> <!--此处代码略...--> <record id="estate_property_type_view_form" model="ir.ui.view"> <field name="name">estate.property.type.form</field> <field name="model">estate.property.type</field> <field name="arch" type="xml"> <form string="Property Type"> <sheet> <!--此处代码略...--> <field name="property_ids" context="{'propertyTypeId': active_id}"> <tree string="Properties"> <field name="name"/> </tree> </field> <!--此处代码略...--> </sheet> </form> </field> </record> </odoo>
打开上述视图(即加载内联Tree视图)时,会自动调用estate.property
模型的read
方法,服务端控制台输出如下:
{'lang': 'en_US', 'tz': 'Europe/Brussels', 'uid': 2, 'allowed_company_ids': [1], 'params': {'action': 165, 'cids': 1, 'id': 1, 'menu_id': 70, 'model': 'estate.property.type', 'view_type': 'form'}, 'propertyTypeId': 1} do something you want
更多示例可参考文档:[odoo 为可编辑列表视图字段搜索添加查询过滤条件](odoo 为可编辑列表视图字段搜索添加查询过滤条件.md)
用于记录集,传递数据给模型方法
模型设计
#!/usr/bin/env python # -*- coding:utf-8 -*- from odoo import models, fields,api class EstatePropertyTag(models.Model): _name = 'estate.property.tag' _description = 'estate property tag' name = fields.Char(string='tag', required=True) color = fields.Integer(string='Color') @api.model def create(self, vals_list): # 通过重写模型的create或者write方法,调用该方法前修改上下文,然后在方法中通过self.env.context获取上下文中的目标key值,进而实现目标需求 res = super(EstatePropertyTag, self).create(vals_list) # 获取上下文目标key值 if not self.env.context.get('is_sync', True): # do something you need return res
>>> self.env['estate.property.tag'].with_context(is_sync=False).create({'name': 'tag4', 'color': 4}).env.context {'lang': 'en_US', 'tz': 'Europe/Brussels', 'is_sync': False} PYTHON 复制 全屏
参考连接
https://www.odoo.com/documentation/14.0/zh_CN/developer/reference/addons/actions.html