动作的加载:

刷新视图页面执行load_views方法

/web/dataset/call_kw/model_name/load_views

在odoo/models.py的BaseModel中有一个load_views方法

@api.model
def load_views(self, views, options=None):
""" Returns the fields_views of given views, along with the fields of
the current model, and optionally its filters for the given action. :param views: list of [view_id, view_type]
:param options['toolbar']: True to include contextual actions when loading fields_views
:param options['load_filters']: True to return the model's filters
:param options['action_id']: id of the action to get the filters
:return: dictionary with fields_views, fields and optionally filters
"""
options = options or {}
result = {} toolbar = options.get('toolbar')
result['fields_views'] = {
v_type: self.fields_view_get(v_id, v_type if v_type != 'list' else 'tree',
toolbar=toolbar if v_type != 'search' else False)
for [v_id, v_type] in views
}
result['fields'] = self.fields_get() if options.get('load_filters'):
result['filters'] = self.env['ir.filters'].get_filters(self._name, options.get('action_id')) return result

odoo/models.py

@api.model
def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
""" fields_view_get([view_id | view_type='form']) Get the detailed composition of the requested view like fields, model, view architecture :param view_id: id of the view or None
:param view_type: type of the view to return if view_id is None ('form', 'tree', ...)
:param toolbar: true to include contextual actions
:param submenu: deprecated
:return: dictionary describing the composition of the requested view (including inherited views and extensions)
:raise AttributeError:
* if the inherited view has unknown position to work with other than 'before', 'after', 'inside', 'replace'
* if some tag other than 'position' is found in parent view
:raise Invalid ArchitectureError: if there is view type other than form, tree, calendar, search etc defined on the structure
"""
View = self.env['ir.ui.view'] # Get the view arch and all other attributes describing the composition of the view
result = self._fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu) # Override context for postprocessing
if view_id and result.get('base_model', self._name) != self._name:
View = View.with_context(base_model_name=result['base_model']) # Apply post processing, groups and modifiers etc...
xarch, xfields = View.postprocess_and_fields(self._name, etree.fromstring(result['arch']), view_id)
result['arch'] = xarch
result['fields'] = xfields # Add related action information if aksed
if toolbar:
bindings = self.env['ir.actions.actions'].get_bindings(self._name)
resreport = [action
for action in bindings['report']
if view_type == 'tree' or not action.get('multi')]
resaction = [action
for action in bindings['action']
if view_type == 'tree' or not action.get('multi')]
resrelate = []
if view_type == 'form':
resrelate = bindings['action_form_only'] for res in itertools.chain(resreport, resaction):
res['string'] = res['name'] result['toolbar'] = {
'print': resreport,
'action': resaction,
'relate': resrelate,
}
return result

addons/base/models/ir_actions.py

@api.model
@tools.ormcache('frozenset(self.env.user.groups_id.ids)', 'model_name')
def get_bindings(self, model_name):
""" Retrieve the list of actions bound to the given model. :return: a dict mapping binding types to a list of dict describing
actions, where the latter is given by calling the method
``read`` on the action record.
"""
cr = self.env.cr
query = """ SELECT a.id, a.type, a.binding_type
FROM ir_actions a, ir_model m
WHERE a.binding_model_id=m.id AND m.model=%s
ORDER BY a.id """
cr.execute(query, [model_name]) # discard unauthorized actions, and read action definitions
result = defaultdict(list)
user_groups = self.env.user.groups_id
for action_id, action_model, binding_type in cr.fetchall():
try:
action = self.env[action_model].browse(action_id)
action_groups = getattr(action, 'groups_id', ())
if action_groups and not action_groups & user_groups:
# the user may not perform this action
continue
result[binding_type].append(action.read()[0])
except (AccessError, MissingError):
continue return result

能否通过修改ir.actions.server的表结构,增加binding_view_id字段,动作定义时设置binding_view_id字段,实现相同模型不同视图显示不通的动作内容。

1、在ir.actions.server中增加字段

binding_view_id = fields.Char(string='my char', default='99999999999')
2、在服务器定义中设置字段
<record id="action_XXX_audit_server" model="ir.actions.server" >
<field name="name">Audit</field>
<field name="model_id" ref="model_gl_voucher"/>
<field name="type">ir.actions.server</field>
<field name="state">code</field>
<field name="code">
action = records.action_server_run()
</field>
<field name="binding_model_id" ref="model_XXX" />
<field name="binding_view_id">66666666666</field>
</record>

3、查看数据库

已经写到数据库了,所以在 get_bindings中加载动作时增加一层过滤就OK,这样就可以实现相同model,相同视图类型,不同视图,显示不同action。

动作的执行:

addons/web/controllers/main.py

@http.route('/web/action/run', type='json', auth="user")
def run(self, action_id):
result = request.env['ir.actions.server'].browse([action_id]).run()
return clean_action(result) if result else False

addons/base/models/ir_actions.py 

@api.multi
def run(self):
""" Runs the server action. For each server action, the
run_action_<STATE> method is called. This allows easy overriding
of the server actions. :param dict context: context should contain following keys - active_id: id of the current object (single mode)
- active_model: current model that should equal the action's model The following keys are optional: - active_ids: ids of the current records (mass mode). If active_ids
and active_id are present, active_ids is given precedence. :return: an action_id to be executed, or False is finished correctly without
return action
"""
res = False
for action in self:
eval_context = self._get_eval_context(action)
if hasattr(self, 'run_action_%s_multi' % action.state):
# call the multi method
run_self = self.with_context(eval_context['env'].context)
func = getattr(run_self, 'run_action_%s_multi' % action.state)
res = func(action, eval_context=eval_context) elif hasattr(self, 'run_action_%s' % action.state):
active_id = self._context.get('active_id')
if not active_id and self._context.get('onchange_self'):
active_id = self._context['onchange_self']._origin.id
if not active_id: # onchange on new record
func = getattr(self, 'run_action_%s' % action.state)
res = func(action, eval_context=eval_context)
active_ids = self._context.get('active_ids', [active_id] if active_id else [])
for active_id in active_ids:
# run context dedicated to a particular active_id
run_self = self.with_context(active_ids=[active_id], active_id=active_id)
eval_context["env"].context = run_self._context
# call the single method related to the action: run_action_<STATE>
func = getattr(run_self, 'run_action_%s' % action.state)
res = func(action, eval_context=eval_context)
return res

  

odoo action的更多相关文章

  1. odoo action方法

    二.动作按钮里面也可以由字段判断: def action_select_sale_order_line(self,cr,uid,ids,date_begin,date_end,context=None ...

  2. (20)odoo中的action

    ---------更新时间18:06 2016-09-18 星期日15:05 2016-03-14 星期一18:07 2016-02-19 星期五---------* 窗口动作   <?xml ...

  3. odoo开发笔记:Server+Action服务器动作自动触发执行

           Odoo的市场定位是SME(中小型企业),这个市场的ERP产品,多如牛毛,产品各具特色.不过,Odoo的自动化处理机制,可以睥睨天下,无人能及.包括一些大型国产软件,如用友.金蝶也不具备 ...

  4. Odoo中的五种Action详解

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826232.html Odoo中的五种action都是继承自ir.actions.actions模型实现的 ...

  5. odoo view field option, action flage 参数

    options JSON object specifying configuration option for the field's widget (including default widget ...

  6. odoo开发笔记--自定义server action页面跳转注意

    场景描述: 在添加自定义服务器动作 “复制全部”后发现直接创建了新的记录,并且直接进入到form保存完的状态. 如何解决: if yourself_obj_copy: return { 'type': ...

  7. Odoo 14 Action URL 生成

    from werkzeug.urls import url_encode url = '/web#%s' % url_encode({ 'action': 'hr.plan_wizard_action ...

  8. Odoo 二次开发教程(三)-第一个Model及Form、Tree视图

    创建完我们的模块,接下来我们就要为我们的模块添加一些对象.今天我们将要创建一个学生对象(tech.student)和一些基本的属性,并将用form和tree视图将其展示出来: 一. 创建tech.st ...

  9. Defining custom settings in Odoo

    Unfortunately Odoo documentation doesn’t seem to include any information about adding new configurat ...

随机推荐

  1. checked,unchecked

    static void Main(string[] args) { byte b1 = 100; byte b2 = 250; //Checked try { byte sum = checked ( ...

  2. 【原】Spring测试类代码

    package test; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.bea ...

  3. updataStateByKey算子的使用

    updataStateByKeyApp.scala import org.apache.spark.SparkConf import org.apache.spark.streaming.{Secon ...

  4. SQL注入:盲注

    盲注简介 所谓的盲注就是在服务器没有错误回显的时候完成的注入攻击. 服务器没有错误回显,对于攻击者来说缺少了非常重要的"调试信息". 盲注分类 1.布尔盲注 布尔很明显Ture和F ...

  5. Centos7安装dubbo与zookeeper服务配置

    目录 环境: 第一步:安装jdk,并且配置环境变量 1.解压jdk: 2.配置环境变量: 3.保存并使文件立即生效: 4.立即重启虚拟机,进行下面的安装 第二步:安装注册中心zookeeper 1.解 ...

  6. 关于微信小程序开发环境苹果IOS真机预览报SSL协议错误问题解决方案

                              微信小程序开发环境苹果IOS真机预览报SSL协议错误问题 原文来自:https://blog.csdn.net/qq_27626333/articl ...

  7. Mysql 数据库部署(解压免安装)

    下载压缩包,解压. 在根目录下添加my.ini, 复制一下内容,保存. [mysqld] skip-grant-tables #绑定IPv4和3306端口 bind-address = 0.0.0.0 ...

  8. Linux---基本目录与文件命令

    一.目录 1.显示工作目录命令pwd 2.改变工作目录命令cd 3.创建目录命令mkdir 二.文件 1.创建空文件命令touch 2.显示文件列表ls 3.复制文件或目录命令cp 4.删除文件或目录 ...

  9. vue router 导航守卫生命周期

    导航守卫 导航守卫主要用来通过跳转或取消的方式守卫导航.有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的.(记住参数或查询的改变并不会触发进入/离开的导航守卫.你可以通过观察$r ...

  10. c# 第17节 二维数组声明、使用

    本节内容: 1:为什么要有二维数组 2:二维数据 3:实例二维数组声明 4:二维数组的使用 1:为什么要有二维数组 2:二维数据声明 3:实例二维数组声明 4:二维数组的使用 foreach遍历 5: ...