You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

Odoo原生客户门户界面

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 21:21:23