Odoo is known for its flexibility, and one of the areas where this strength truly stands out is website development. Whether you want to showcase custom content, build unique landing pages, or extend business logic to the frontend, Odoo makes it possible through its powerful website framework.
In this guide, we’ll walk through how to create a custom web page in Odoo 19 by building a simple module. We will define the module structure, write a controller, design a QWeb template, and expose the page through the website menu.
Module Structure
Start by creating a new custom module named custom_web_page.
This module will include:
- A controller to respond to web requests
- A QWeb template for the UI
- A website menu entry for navigation
Your directory should look like this:
custom_web_page/
+-- __init__.py
+-- __manifest__.py
+-- controllers/
¦ +-- __init__.py
¦ +-- main.py
+-- views/
+-- templates.xml
Purpose of Each File
- __manifest__.py – Contains module metadata and dependencies.
- controllers/ – Holds Python files that handle website requests.
- views/ – Contains QWeb templates that define the page layout.
- __init__.py files – Ensure the components are loaded by Odoo.
Creating the Manifest
The manifest file is the entry point of your module. It tells Odoo what your module contains and which modules it depends on.
# -*- coding: utf-8 -*-
{
'name': 'Custom Web Page',
'version': '19.0.1.0.0',
'summary': 'A module to create a custom web page in Odoo.',
'author': 'Your Name',
'website': 'https://www.yourwebsite.com',
'category': 'Website',
'depends': [
'base','website',
],
'data': [
'views/templates.xml',
],
'installable': True,
'application': False,
'auto_install': False,
}
Here, the website module is a required dependency, since our page will be accessible through the frontend.
Building the Controller
Controllers in Odoo manage HTTP routes and responses.
Our controller will handle the /hello-odoo URL and render a template.
# -*- coding: utf-8 -*-
from odoo import http
from odoo.http import request
class HelloWorld(http.Controller):
@http.route('/hello-odoo', type='http', auth='public', website=True)
def hello_page(self, **kwargs):
"""
This controller handles the request for the /hello-odoo page.
It renders a QWeb template and passes a dynamic value.
"""
user_name = request.env.user.name if request.env.user.id else 'Guest'
return request.render('custom_web_page.hello_page_template', {
'user_name': user_name,
})
Key Elements Explained
- @http.route – Registers a public URL.
- auth='public' – Allows both logged-in users and guests to access the page.
- website=True – Indicates that this route is part of the website.
- request.render() – Loads and renders a QWeb template.
The controller passes a simple dynamic value—user_name—to the template.
Creating the QWeb Template
Odoo uses QWeb as its templating engine for website pages.
Our template will display a welcome message along with the user's name.
views/templates.xml:
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- The QWeb Template for our Custom Page -->
<template id="hello_page_template" name="Hello Odoo Page">
<t t-call="website.layout">
<div id="wrap" class="oe_structure">
<div class="container">
<div class="row">
<div class="col-12 text-center mt-5">
<h1>Welcome to our Custom Odoo Page!</h1>
<p class="lead">
Hello, <t t-esc="user_name"/>! This page was rendered by a custom controller.
</p>
</div>
</div>
</div>
</div>
</t>
</template>
<!-- Menu Item to link to our new page -->
<record id="hello_page_menu" model="website.menu">
<field name="name">Hello Page</field>
<field name="url">/hello-odoo</field>
<field name="parent_id" ref="website.main_menu"/>
<field name="sequence" type="int">99</field>
</record>
</data>
</odoo>
What This Template Includes
- t-call="website.layout" – Uses the standard Odoo layout with header, footer, etc.
- Dynamic content – Displays the current user’s name.
- A menu item – Automatically adds a label “Hello Page” to the website's menu bar.
Initializing the Module
To load the controller, add the following to your module’s __init__.py:
__init__.py:
# -*- coding: utf-8 -*-
from . import controllers
controllers/__init__.py:
# -*- coding: utf-8 -*-
from . import main
Installing and Testing the Module
Once your module is ready:
- Place it inside your Odoo addons directory.
- Restart the Odoo server.
- Install the module via Apps.
- Visit /hello-odoo or click Hello Page in the website menu.
You should now see a personalized welcome message rendered by your custom page.
Creating custom web pages in Odoo 19 is straightforward once you understand the structure of controllers, templates, and module design.With this foundation, you can build more complex pages—displaying records, integrating forms, calling APIs, or extending business logic into the website.
Custom web pages offer endless possibilities for enhancing your Odoo frontend experience, making your system both functional and user-friendly.
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.