7

odoo context上下文用法总结 - 授客

 1 year ago
source link: https://www.cnblogs.com/shouke/p/17135902.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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[源代码]

返回附加到扩展上下文的此记录集的新版本。

扩展上下文是提供的合并了overridescontext,或者是合并了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}

https://www.odoo.com/documentation/14.0/zh_CN/developer/reference/addons/actions.html


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK