Enable Dark Mode!
By: Jibin

How to Customize Odoo 15 Website Templates

Technical Odoo 15 Website&E-commerce

Odoo 15 is more advanced and has more features to edit the website from the UI itself from the drag and drop(snippets) feature. There we can see many options to build a website or customize the website from the UI itself with the help of the Odoo Website Builder. To know more about creating or customizing a website from UI itself, please visit our blog Odoo 14 Website Builder.
In this blog, we will discuss how to customize the website template from the backend or through code.

We can do this by inheriting the website template or by overriding the template.
To know more about these two, you can click How to Customize Odoo 14 Website Templates.
So here, I will take the portal user details from View and add a field to the form View by inheriting the template.


On this Form, I will add a new field and save the value to the customer form[res.partner form view].

<template id="portal_my_details_inherit" inherit_id="portal.portal_my_details"  name="User Deatails Inherit">
<xpath expr="//label[@for='email']/parent::div" position="after">
<div t-attf-class="form-group #{error.get('alternative_email') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label label-optional" for="alternative_email">Alternative Email</label>
<input type="email" name="alternative_email" t-attf-class="form-control #{error.get('alternative_email') and 'is-invalid' or ''}" t-att-value="alternative_email or partner.alternative_email" />

The template ID for this form is portal_my_details and is in the portal module. So I am inheriting the template and adding the new field after the email field. The inherit id attributes help in inheriting the original template from the portal, and XPath will help position the new field. The XPath expression has parent::div at the end; this will find the parent div of the field, which helps add the new field after the email field. The new field I will add is an alternative email, so after positioning the XPath, add the area and its label.


On clicking the confirm button in the form, we need to save the details to the res.partner model. Currently, it will keep all the values except the alternative email. To do that first, I am going to inherit res.partner and add the field.

class ResPartner(models.Model):
   _inherit = "res.partner"
   alternative_email = fields.Char("Email")

So, here I am adding a field for alternative emails. The confirm button or the portal form has an action /my/account defined, which on clicking the button will call a controller function.

from odoo.http import content_disposition, Controller, request, route
from odoo.addons.portal.controllers.portal import CustomerPortal
from odoo import http, _

class CustomerPortalInherit(CustomerPortal):
   MANDATORY_BILLING_FIELDS = ["name", "phone", "email", "street", "city", "country_id"]
   OPTIONAL_BILLING_FIELDS = ["zipcode", "state_id", "vat", "company_name", "alternative_email"]
   @route(['/my/account'], type='http', auth='user', website=True)
   def account(self, redirect=None, **post):
       print("xdcjsknfk ", post)
       values = self._prepare_portal_layout_values()
       print(" nn j", values)
       partner = request.env.user.partner_id
           'error': {},
           'error_message': [],
       if post and request.httprequest.method == 'POST':
           error, error_message = self.details_form_validate(post)
           values.update({'error': error, 'error_message': error_message})
           print("Xcn...... ii a", values)
           if not error:
               values = {key: post[key] for key in self.MANDATORY_BILLING_FIELDS}
               values.update({key: post[key] for key in self.OPTIONAL_BILLING_FIELDS if key in post})
               for field in set(['country_id', 'state_id']) & set(values.keys()):
                       values[field] = int(values[field])
                       values[field] = False
               values.update({'zip': values.pop('zipcode', '')})
               if redirect:
                   return request.redirect(redirect)
               return request.redirect('/my/home')
       countries = request.env['res.country'].sudo().search([])
       states = request.env['res.country.state'].sudo().search([])
           'partner': partner,
           'countries': countries,
           'states': states,
           'has_check_vat': hasattr(request.env['res.partner'], 'check_vat'),
           'redirect': redirect,
           'page_name': 'my_details',
       response = request.render("portal.portal_my_details", values)
       response.headers['X-Frame-Options'] = 'DENY'
       return response

Here I am importing the CustomerPortal

Class from the portal module, we have to define the mandatory and optional fields.

MANDATORY_BILLING_FIELDS = ["name", "phone", "email", "street", "city", "country_id"]
   OPTIONAL_BILLING_FIELDS = ["zipcode", "state_id", "vat", "company_name", "alternative_email"]

If not, the form will show an error for an unknown field.
Actually, we don't need to do anything much with this controller because the newly added field in the form and res.partner have the same name, and the controller, post, and values variable have the area and its values, which will write directly into the res.partner model.
We can give the email widget in the XML view defined for the res.partner form for the form validation.

<record id="trader_inherit_form" model="ir.ui.view">
       <field name="name">website.partner</field>
       <field name="model">res.partner</field>
       <field name="inherit_id" ref="base.view_partner_form"/>
       <field name="arch" type="xml">
           <field name="email" position="after">
               <field name="alternative_email" widget="email"/>

But this widget alone will not do the proper form validation.The CustomerPortal class has another function[details_form_validate()] which does the validation for fields.Hence, adding a line for validating the new field will help to properly validate the field.

If you need any assistance in odoo, we are online, please chat with us.


Leave a comment




Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635



Cybrosys Limited
Alpha House,
100 Borough High Street, London,
SE1 1LB, United Kingdom



Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.



Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message