在Odoo的定制化开发中,经常需要对前端页面的元素进行调整,比如修改原有表单的显示内容、新增自定义按钮、处理前端的异步请求等。Odoo提供了视图继承和控制器扩展的机制,开发者可以在不修改官方源码的前提下,完成前端元素的各类操作。

Odoo前端相关基础概念
Odoo的前端页面主要通过QWeb模板引擎渲染,视图文件定义了页面的结构和元素,控制器则负责处理前端的请求并返回对应的数据。常见的视图类型包括表单视图、列表视图、看板视图等,每种视图都有对应的XML定义规则。
需要操作的前端元素通常分为两类:一类是静态的页面结构元素,比如按钮、输入框、文本标签等;另一类是动态的交互逻辑,比如点击按钮触发请求、页面加载时获取数据等。这两类操作分别对应视图扩展和控制器扩展两种实现方式。
通过扩展视图操作前端静态元素
视图扩展的核心是继承已有的视图,通过<xpath>表达式定位到需要修改的元素位置,再进行新增、替换、删除等操作。下面以修改销售订单表单视图为例,在原有视图中新增一个自定义文本字段的显示。
第一步:定义模型新增自定义字段
首先在自定义模块的模型中新增需要展示的字段,这里在sale.order模型中新增一个custom_remark字段:
from odoo import models, fields
class SaleOrder(models.Model):
_inherit = 'sale.order'
# 新增自定义备注字段
custom_remark = fields.Char(string='自定义备注')
第二步:继承原有视图新增元素
接下来编写视图XML文件,继承销售订单的表单视图,在原有备注字段后面新增自定义备注字段的显示:
<odoo>
<record id="view_sale_order_form_inherit_custom" model="ir.ui.view">
<field name="name">sale.order.form.inherit.custom</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='note']" position="after">
<field name="custom_remark"/>
</xpath>
</field>
</record>
</odoo>
上述代码中,inherit_id指定了要继承的原有视图,xpath的expr属性用于定位原有视图中的note字段,position="after"表示在定位元素之后新增内容,这样就完成了前端静态元素的添加操作。
通过扩展控制器处理前端交互逻辑
如果需要对前端元素添加交互逻辑,比如点击按钮发送请求获取数据,就需要扩展控制器。Odoo的控制器通过路由装饰器定义访问路径,前端可以通过Ajax请求调用对应的控制器方法。
第一步:编写自定义控制器
在自定义模块的controllers目录下新建main.py文件,编写控制器逻辑:
from odoo import http
from odoo.http import request
class CustomController(http.Controller):
# 定义路由,支持GET和POST请求
@http.route('/custom/get_order_info', type='json', auth='user', methods=['POST'])
def get_order_info(self, order_id):
# 获取销售订单记录
order = request.env['sale.order'].browse(order_id)
if order.exists():
return {
'name': order.name,
'partner_name': order.partner_id.name,
'custom_remark': order.custom_remark
}
return {'error': '订单不存在'}
第二步:前端调用控制器方法
在之前的视图中新增一个按钮,点击按钮时调用上述控制器获取订单信息,修改视图XML文件:
<odoo>
<record id="view_sale_order_form_inherit_custom" model="ir.ui.view">
<field name="name">sale.order.form.inherit.custom</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='note']" position="after">
<field name="custom_remark"/>
<button string="获取订单信息" type="button" class="btn-primary" onclick="getOrderInfo()"/>
</xpath>
<script>
function getOrderInfo() {
var orderId = $('.o_form_view').data('record-id');
$.ajax({
url: '/custom/get_order_info',
type: 'POST',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify({
'jsonrpc': '2.0',
'params': {
'order_id': orderId
}
}),
success: function(res) {
if (res.result.error) {
alert(res.result.error);
} else {
alert('订单名称:' + res.result.name + ',客户:' + res.result.partner_name);
}
}
});
}
</script>
</field>
</record>
</odoo>
上述代码在视图中新增了一个按钮,点击按钮会触发getOrderInfo函数,通过Ajax请求调用自定义控制器,获取订单信息后弹出提示,完成了前端元素的交互逻辑操作。
注意事项
- 视图继承时,
xpath表达式要准确匹配原有元素,避免定位错误导致视图加载异常。 - 控制器路由的
auth参数要根据实际需求设置,公开接口可以设置为public,需要登录的接口设置为user。 - 前端调用控制器时,要符合Odoo的JsonRpc请求格式,参数需要放在
params字段中传递。 - 自定义模块的
__manifest__.py文件中要正确声明依赖,比如上述示例需要依赖sale模块。
通过上述两种方式,就可以完成Odoo中大部分前端元素的操作需求,既保证了官方源码的完整性,也满足了项目的定制化要求。