odoo context上下文用法总结
环境
odoo-14.0.post20221212.tar
context用法总结
获取上下文
1 2 3 4 5 | >>> 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
1 2 3 4 5 | # 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <?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> |
说明:
1 | <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
所代表的过滤器,否则不开启。
用于搜索视图,添加分组查询条件
视图设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?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': '分组字段名称'
用于视图对象按钮,传递数据给模型方法
模型设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #!/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 |
视图设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?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列表)中,否则会出现类似错误提示:
1 | Field offer_count used in context.offerCount ({ 'offerCount' : offer_count}) must be present in view but is missing. |
点击界面按钮后,服务端打印日志如下
1 | 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)
,服务端控制台会收到类似如下告警(虽然点击按钮后,服务端不会抛异常):
1 | 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)
,则点击页面确认按钮时,服务端会报错误,如下:
1 | TypeError: action_confirm2() takes 1 positional argument but 2 were given |
用于视图动作按钮,传递数据给动作关联的视图
视图设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?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关联视图设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <?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> |
传递数据给视图关系字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <?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> |
用于视图关系字段,传递数据给模型方法
模型设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #!/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) |
视图设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?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
方法,服务端控制台输出如下:
1 2 | { '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)
用于记录集,传递数据给模型方法
模型设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #!/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 |
1 2 | >>> 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 } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示