Enable Dark Mode!
how-to-modify-existing-web-pages-in-odoo-19.jpg
By: Ayana R

How to Modify Existing Web Pages in Odoo 19

Technical Odoo 19 Odoo Enterprises Odoo Community

In Odoo 19, the website module powers dynamic, editable web pages using QWeb templates, controllers, and views. Modifying existing pages—such as the homepage, product pages, or shop—without altering core code is a best practice. This ensures upgrade compatibility and maintainability. Odoo's inheritance system lets you extend templates and views safely.

This guide walks you through creating a custom module to programmatically modify web pages. We'll use a practical example: adding a "Top Selling Products" section to the homepage (website.homepage template). This involves:

  • Extending models for data.
  • Customizing controllers for logic.
  • Inheriting templates for UI changes.

By the end, you'll have a reusable module. All code is based on Odoo 19's framework, with inheritance via XPath for precise modifications.

Step 1: Set Up the Custom Module Structure

Create the following files in custom_website_mods/:

custom_website_mods/
+-- __init__.py
+-- __manifest__.py
+-- models/
¦   +-- __init__.py
¦   +-- product_template.py
+-- controllers/
¦   +-- __init__.py
¦   +-- main.py
+-- views/
    +-- homepage_templates.xml
  • __init__.py (root): from . import models, controllers
  • models/__init__.py: from . import product_template
  • controllers/__init__.py: from . import main

Module Manifest (__manifest__.py)

Define dependencies and load files.

{
    'name': 'Custom Website Modifications',
    'version': '19.0.1.0.0',
    'category': 'Website',
    'summary': 'Modify existing web pages through code',
    'depends': ['website', 'website_sale'],  # Core website and eCommerce
    'data': [
        'views/homepage_templates.xml',
    ],
    'installable': True,
    'auto_install': False,
}

Install the module via Apps > Update Apps List > Search "Custom Website Modifications" > Install.

Step 2: Extend Models for Custom Data

To display "top-selling" products, add a boolean field to product.template for manual tagging (or compute dynamically from sales orders).

In models/product_template.py:

from odoo import fields, models
class ProductTemplate(models.Model):
    _inherit = 'product.template'
    is_top_selling = fields.Boolean(
        string='Top Selling',
        help='Mark this product as top-selling for homepage display.'
    )

This inherits the existing product.template model without modifying the original. Update the module to apply the field (it'll appear in product forms).

Step 3: Customize Controllers for Logic

Controllers handle routing and data preparation. Inherit website to extend the homepage route.

In controllers/main.py:

import odoo.http as http
from odoo.http import request
from odoo.addons.website.controllers.main import Website
class WebsiteTopSelling(Website):
    @http.route('/', type='http', auth='public', website=True)
    def index(self, **kw):
        # Call parent to get default homepage data
        response = super(WebsiteTopSelling, self).index(**kw)
        
        # Fetch top-selling products (limit 4, published only)
        top_products = request.env['product.template'].search([
            ('is_top_selling', '=', True),
            ('website_published', '=', True),
        ], limit=4, order='sales_count desc')
        
        # Pass to template
        response.qcontext['top_selling_products'] = top_products
        return response

This overrides the root route (/) to inject custom data into the QContext, making top_selling_products available in templates. Restart Odoo and update the module.

Step 4: Inherit Templates for UI Modifications

Use QWeb inheritance to modify the website.homepage template. Add a new section inside the main wrapper.

In views/homepage_templates.xml:

<?xml version="1.0" encoding="UTF-8"?>
<odoo>
    <template id="homepage_top_selling" inherit_id="website.homepage" name="Top Selling Products Section">
        <xpath expr="//div[@id='wrap']" position="inside">
            <div class="container mt-5 mb-5">
                <h2 class="text-center mb-4">Top Selling Products</h2>
                <div class="row">
                    <t t-foreach="top_selling_products" t-as="product">
                        <div class="col-md-3 mb-4">
                            <div class="card h-100">
                                <img t-att-src="product.image_1920 or '/web/static/src/img/placeholder.png'" 
                                     class="card-img-top" alt="Product Image" style="height: 200px; object-fit: cover;"/>
                                <div class="card-body d-flex flex-column">
                                    <h5 class="card-title"><t t-esc="product.name"/></h5>
                                    <p class="card-text flex-grow-1"><t t-esc="product.list_price"/> €</p>
                                    <a t-att-href="'/shop/product/%s' % product.id" class="btn btn-primary mt-auto">View Product</a>
                                </div>
                            </div>
                        </div>
                    </t>
                </div>
            </div>
        </xpath>
    </template>
</odoo>
  • inherit_id="website.homepage": Targets the existing homepage template.
  • <xpath>: Specifies where to insert (inside #wrap div).
  • QWeb directives like t-foreach loop over products; t-esc escapes output for safety.

Update the module. Visit your homepage (/)—the section appears if products are marked as top-selling.

Step 5: Advanced Modifications

Modifying Menus

To rename/hide menus (e.g., change "Shop" to "Products"), inherit website.menu records.

Example in a new XML file (views/menu_mods.xml):

<odoo>
    <record id="shop_menu_inherit" model="website.menu">
        <field name="inherit_id" ref="website_sale.menu_shop_main"/>
        <field name="name">Products</field>
    </record>
    
    <!-- Hide Blog Menu -->
    <record id="blog_menu_hide" model="website.menu">
        <field name="inherit_id" ref="website_blog.menu_blog_link"/>
        <field name="is_visible" eval="False"/>
    </record>
</odoo>

Add to __manifest__.py data list. This updates menu records without code hacks.

Custom Pages or Routes

For new pages, create templates and routes (see Odoo docs for full how-to)

<template id="custom_page" name="Custom Page" page="True">
    <t t-call="website.layout">
        <div id="wrap" class="container">
            <h1>My Custom Page</h1>
            <!-- Content -->
        </div>
    </t>
</template>

Route in controller: @http.route('/custom', type='http', auth='public', website=True).

Styling with CSS/JS

Add assets to __manifest__.py:

'assets': {
    'web.assets_frontend': [
        'custom_website_mods/static/src/scss/custom.scss',
        'custom_website_mods/static/src/js/custom.js',
    ],
},

Inherit layouts for global changes, e.g., .

Modifying existing web pages in Odoo 19 through code is both powerful and safe when done using Odoo’s inheritance mechanisms—model inheritance, controller overrides, and QWeb template inheritance with XPath. By creating a custom module, you can extend the homepage, product pages, menus, or any website component without touching core files, ensuring upgrade compatibility and clean maintainability.

To read more about How to Modify Existing Web Pages in Odoo 18, refer to our blog How to Modify Existing Web Pages in Odoo 18.


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



0
Comments



Leave a comment



whatsapp_icon
location

Calicut

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

location

Kochi

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

location

Bangalore

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

Send Us A Message