Odoo客户门户添加自定义UI元素 新增plan标签页展示关联图片

Odoo客户门户新增自定义「业务计划」标签实现方案
全流程走Odoo原生继承逻辑实现,无需修改核心代码,交互、样式完全对齐原生标签体验:
1. 前置模型与权限配置
- 确认业务计划模型与客户(
res.partner)的关联关系:在业务计划模型中定义指向res.partner的必填Many2one字段partner_id,在res.partner中反向定义One2one字段plan_id关联业务计划模型,配置ondelete='cascade'避免脏数据。 - 配置访问权限:在模块的
ir.model.access.csv中,为门户用户组(base.group_portal)添加业务计划模型的读权限,避免前台访问报403。如果业务计划图片以附件形式存储,需同步给门户用户组开对应附件的读权限。
2. 继承门户控制器添加路由
继承原生CustomerPortal控制器,添加对应路由和门户首页计数逻辑,和原生标签逻辑完全对齐:
from odoo import http from odoo.addons.portal.controllers.portal import CustomerPortal from odoo.http import request class PortalPlanController(CustomerPortal): def _prepare_home_portal_values(self, counters): values = super()._prepare_home_portal_values(counters) current_partner = request.env.user.partner_id if 'plan_count' in counters: # 给标签添加计数角标,和原生发票、报价标签的角标逻辑一致 values['plan_count'] = 1 if current_partner.sudo().plan_id else 0 return values @http.route(['/my/plan'], type='http', auth='user', website=True) def portal_my_plan(self, **kwargs): current_partner = request.env.user.partner_id plan_record = current_partner.sudo().plan_id # 无对应计划时返回提示页 if not plan_record: return request.render("your_module.portal_plan_empty", {}) # 传递页面通用参数,保证导航高亮、布局统一 render_values = { 'plan': plan_record, 'page_name': 'plan', 'breadcrumbs': [ ('个人中心', '/my'), ('业务计划', '/my/plan') ] } return request.render("your_module.portal_plan_page", render_values)
注:以上代码适配Odoo14及以上版本,13及更早版本需替换计数方法为对应版本的原生门户计数实现。
3. 继承模板添加导航入口与展示页
通过模板继承直接复用原生门户的布局、菜单样式,无需自定义CSS:
<odoo> <!-- 继承门户侧边菜单,新增业务计划标签 --> <template id="portal_menu_add_plan" inherit_id="portal.portal_my_home"> <xpath expr="//div[contains(@class, 'o_portal_menu_list')]//t[last()]" position="after"> <t t-call="portal.portal_my_home_menu_item"> <t t-set="name">业务计划</t> <t t-set="url">/my/plan</t> <t t-set="count" t-value="plan_count"/> <t t-set="icon">fa-file-image-o</t> </t> </xpath> </template> <!-- 业务计划展示页,复用原生门户布局 --> <template id="portal_plan_page" name="我的业务计划"> <t t-call="portal.portal_layout"> <div class="container py-4"> <h3>我的专属业务计划</h3> <div class="card mt-3 p-3"> <!-- 替换为你的模型名、二进制图片字段名 --> <img t-att-src="'/web/image/your.plan.model/%s/plan_image_field' % plan.id" class="img-fluid" alt="业务计划"/> </div> </div> </t> </template> <!-- 无计划提示页 --> <template id="portal_plan_empty" name="暂无业务计划"> <t t-call="portal.portal_layout"> <div class="alert alert-info mt-4"> 暂未查询到您的专属业务计划,请联系对接客服获取。 </div> </t> </template> </odoo>
4. 体验对齐校验点
- 菜单高亮:模板中传递的
page_name='plan'参数会自动触发原生菜单的高亮逻辑,无需额外写样式判断 - 权限控制:正式环境可去掉控制器里的
sudo()调用,完全依靠配置的模型访问权限做校验,避免越权访问 - 图片加载:如果图片存储在独立的附件表中,需确保附件的
res_model、res_id关联正确,且门户用户有对应附件的读权限,避免图片加载403
内容的提问来源于stack exchange,提问作者unnamed-dev
相关产品推荐
相关产品推荐

