Introduction to Odoo Controllers and Routes
Odoo Controllers and Routes empower developers to create dynamic and responsive websites with ease. In this tutorial, we explain how you can build and customize an Odoo website controller, define clear routes, and render QWeb templates to display data effectively. We begin with a simple example and gradually increase complexity while always using active voice and smooth transition words. Furthermore, you will see how Odoo Controllers and Routes integrate with Odoo’s powerful templating engine to bring data to life on your website. We use keyphrases such as Odoo website controller and route configuration throughout this guide. For more details on Odoo’s official practices, please visit the Odoo Documentation.
In this tutorial, we will walk you through every step—from setting up your system and creating your first controller to advanced features like dynamic data binding and debugging. You will learn how to structure your code, create clean and maintainable modules, and leverage Odoo’s built-in mechanisms to develop a robust website. Let us start with the basics and then move into more sophisticated implementations.
Understanding Odoo Controllers and Routes
Odoo Controllers and Routes form the backbone of any Odoo web module. They manage the communication between HTTP requests and the server-side logic. Every time a user makes a request by visiting a URL, Odoo processes the request by invoking the appropriate controller method through a defined route. For instance, when you define a route such as:
@http.route('/odoodiscussions/classes', auth='public', website=True)
def display_classes(self, **kwargs):
template = 'od_openacademy_website.odoodiscussions_classes'
return request.render(template)
the controller listens for incoming requests at the /odoodiscussions/classes URL. Moreover, it uses the Odoo QWeb templating engine to display the associated HTML content. In the code above, the function display_classes is actively executed each time the route is accessed, and it immediately renders the template that contains your website content.
Transitioning from the abstract to the practical, we now examine the structure of a typical controller and explore how to integrate routes and templates.
Setting Up Your Environment for Odoo Development
Before you write any code, you must prepare your development environment. First, install the latest version of Odoo (for example, Odoo 16) and ensure that Python and PostgreSQL are installed on your system. You must also install necessary dependencies. We recommend using Visual Studio Code or PyCharm to structure your code in an organized manner.
Next, you should download a scaffold for your module. For example, run the following command in your terminal:
odoo scaffold od_openacademy_website /path/to/your/addons
This command creates a module named od_openacademy_website with directories for controllers, models, views, and additional initialization files. Consequently, you will have a complete structure to build upon. Transitioning smoothly into development, you can start integrating controllers and routes to display dynamic content.
Building a Basic Odoo Website Controller
In this section, we build a basic controller that demonstrates the relationship between Odoo Controllers and Routes and the QWeb templating system.
Creating Routes and Rendering QWeb Templates
Start by creating a Python file in your module’s controllers/ directory (e.g., main.py). In this file, add the following code:
from odoo import http
from odoo.http import request
class OdooDiscussions(http.Controller):
@http.route('/odoodiscussions/classes', auth='public', website=True)
def display_classes(self, **kwargs):
template = 'od_openacademy_website.odoodiscussions_classes'
return request.render(template)
This code defines a new controller class named OdooDiscussions that inherits from http.Controller. Notice that the decorator @http.route assigns the URL /odoodiscussions/classes to the method display_classes. Furthermore, the parameter auth='public' ensures that anyone can access the route, and website=True integrates it with Odoo’s website module. Finally, the method uses the request.render() method to render the template identified by 'od_openacademy_website.odoodiscussions_classes'.
Detailed Explanation of the Code
We now explain the code step by step using clear and active sentences:
- Importing Core Modules:
The code imports the necessary modules from Odoo:
from odoo import http
from odoo.http import request
This action ensures that you have access to Odoo’s HTTP controllers and rendering methods.
- Defining the Controller Class:
Next, a class calledOdooDiscussionsis defined, which inherits fromhttp.Controllerso that Odoo can identify it as a controller:
class OdooDiscussions(http.Controller):
- Mapping the Route:
The@http.routedecorator maps the URL/odoodiscussions/classesdirectly to the functiondisplay_classes. Withauth='public'andwebsite=True, the route becomes accessible to all users through the website:
@http.route('/odoodiscussions/classes', auth='public', website=True)
- Rendering the QWeb Template:
Inside the method, a template ID is stored, and then therequest.render()function is called to display that template:
def display_classes(self, **kwargs):
template = 'od_openacademy_website.odoodiscussions_classes'
return request.render(template)
This process enables the separation of business logic from the presentation layer, which simplifies future enhancements.
Creating the QWeb Template
In tandem with the controller code, you must define the corresponding QWeb template. Create an XML file (e.g., views/template.xml) in your module’s views/ directory with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<template id="odoodiscussions_classes" name="Odoo discussions Classes">
<title>Odoo discussions</title>
<h3>Classes</h3>
<ul>
<li>Math</li>
<li>English</li>
<li>Programming</li>
</ul>
</template>
</odoo>
Explanation of the QWeb Template
This XML file performs several tasks:
- Root Element:
The<odoo>tag serves as the container for all Odoo XML data. - Template Definition:
The<template>tag defines a QWeb template with an ID ofodoodiscussions_classes. Itsnameattribute provides a human-readable description. - Page Elements:
The tags<title>and<h3>set the page’s title and header. The unordered list<ul>then contains several<li>elements representing different classes (Math, English, and Programming).
Thus, when the controller calls request.render('od_openacademy_website.odoodiscussions_classes'), it loads the template, and the browser displays the content accordingly.
Linking the Controller with the Template
After you have created both the controller and the template, you must ensure they communicate effectively. In the controller, the line:
return request.render(template)
calls the QWeb rendering mechanism, which locates the template by its unique ID and then dynamically generates HTML output. Transitioning from controller configuration to final output, the rendered page will display the list of classes, as outlined in the XML file.
Moreover, you should verify that the template is referenced correctly in your module’s manifest file (__manifest__.py). For example:
{
'name': 'Odoo OpenAcademy Website',
'summary': 'Module to display data using Odoo Controllers and Routes',
'author': 'Your Name',
'depends': ['website'],
'data': [
'views/template.xml',
],
'installable': True,
'application': True,
}
This manifest file registers your QWeb template and ensures that Odoo loads it during module installation.
Advanced Controller Customizations
Once you understand the basics, you can explore advanced techniques to enhance your module’s functionality. Transitioning into more challenging topics, we now discuss how to pass dynamic data to templates and incorporate additional optimizations.
Passing Dynamic Data to the QWeb Template
Instead of rendering a static template, you can pass dynamic data from your controller to the view. Assume you have a model defined for classes. You might have a model file (e.g., models/openacademy.py) containing:
from odoo import models, fields
class Class(models.Model):
_name = 'openacademy.class'
_description = 'Class'
name = fields.Char(string='Class Name', required=True)
description = fields.Text(string='Description')
You can query this model within your controller to fetch actual data. For example:
from odoo import http
from odoo.http import request
class OdooDiscussions(http.Controller):
@http.route('/odoodiscussions/classes', auth='public', website=True)
def display_classes(self, **kwargs):
classes = request.env['openacademy.class'].sudo().search([])
template = 'od_openacademy_website.odoodiscussions_classes'
return request.render(template, {'classes': classes})
Modifying the Template to Display Dynamic Data
Next, update your QWeb template to loop through the records passed from the controller. Replace the static list with a dynamic loop:
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<template id="odoodiscussions_classes" name="Odoo discussions Classes">
<title>Odoo discussions</title>
<h3>Classes</h3>
<t t-if="classes and classes != []">
<ul>
<t t-foreach="classes" t-as="cls">
<li>
<strong><t t-esc="cls.name"/></strong>:
<t t-esc="cls.description"/>
</li>
</t>
</ul>
</t>
<t t-else="">
<p>No classes available.</p>
</t>
</template>
</odoo>
Explanation of the Dynamic Template Changes
- Dynamic Condition Check:
The<t t-if="classes and classes != []">tag checks if there are records available. This condition ensures that the template only renders the list if data exists. - Looping over Data:
The<t t-foreach="classes" t-as="cls">directive iterates over every class record, assigning each to the variablecls, and then displays itsnameanddescription. - Fallback Message:
The<t t-else="">block displays a fallback message when no class data is available.
These modifications allow you to display actual data from your Odoo model dynamically, which greatly enhances your website’s interactivity.
Incorporating Logging and Debugging in Controllers
To facilitate troubleshooting and ensure your module runs smoothly, you can incorporate logging statements within your controllers. For example, add the logging module to capture method calls:
import logging
from odoo import http
from odoo.http import request
_logger = logging.getLogger(__name__)
class OdooDiscussions(http.Controller):
@http.route('/odoodiscussions/classes', auth='public', website=True)
def display_classes(self, **kwargs):
_logger.info("display_classes called with kwargs: %s", kwargs)
classes = request.env['openacademy.class'].sudo().search([])
template = 'od_openacademy_website.odoodiscussions_classes'
return request.render(template, {'classes': classes})
Explanation
- Logging Setup:
The_loggerobject records logs for debugging and troubleshooting. - Active Logging Statement:
The log statement in thedisplay_classesmethod logs any keyword arguments passed with the request. This log is useful for pinpointing issues when your module behaves unexpectedly.
Using such logging techniques, you can effectively monitor your module’s performance and identify areas that may need improvement.
Best Practices for Odoo Controllers and Routes
To ensure maintainability and scalability, follow these best practices:
- Keep Functions Focused:
Write each controller function with a single responsibility. Use descriptive names likedisplay_classesto clearly communicate the function’s purpose. Always use active verbs in your code comments. - Leverage Transition Words:
Use clear transition words such as “firstly,” “next,” “then,” and “finally” in both code comments and documentation to ensure that your logic flows naturally. - Uniformly Use Keyphrases:
Consistently distribute the keyphrase Odoo Controllers and Routes and its synonyms (such as Odoo website controller and route configuration) throughout your code and documentation. This practice not only improves readability but also reinforces key concepts for beginners. - Structure Your Code Clearly:
Divide your code into logical sections by grouping related functionality. Use inline comments and modular functions, which aid both maintenance and future development. - Implement Error Handling and Logging:
Proactively add logs and error checks to catch issues early. This approach saves time during debugging and ensures a better user experience. - Follow Odoo Standards:
Use the official Odoo guidelines for coding styles, file structures, and XML templating. Always consult the Odoo Documentation for the latest recommendations.
Troubleshooting Common Issues
Even though you follow best practices, you might encounter common issues. Here are a few techniques to address them:
- Template Not Rendering:
Verify that the template ID inrequest.render()precisely matches the ID defined in your XML file. Also, ensure that the XML file is correctly referenced in the manifest. - Access Rights Issues:
Confirm that the route’s authentication parameter (auth='public'orauth='user') corresponds to your security needs. Check the server logs for any permission-related warnings. - No Data in Template:
If dynamic data does not display, ensure that your model records exist in the database. Use Odoo’s shell or the user interface to create sample data and observe the rendered output. - Logging Absence:
If your logging messages do not appear, verify that the logging configuration in your Odoo instance is set to capture the correct log level (typically INFO or DEBUG).
By actively using these troubleshooting steps and best practices, you can resolve issues promptly and continuously improve your module.
Extending the Module with More Features
After mastering the basic implementation, you can extend your module further. Transitioning to advanced customization, consider the following enhancements:
Adding URL Parameters to Routes
You can define routes with dynamic parameters to display detailed information. For example, if you want to show details for a single class, modify your controller as follows:
@http.route('/odoodiscussions/classes/<int:class_id>', auth='public', website=True)
def display_class_detail(self, class_id, **kwargs):
class_record = request.env['openacademy.class'].sudo().browse(class_id)
if not class_record:
return request.render('od_openacademy_website.class_not_found', {})
return request.render('od_openacademy_website.class_detail', {'class': class_record})
This code snippet actively fetches a class record using its ID from the URL, then renders a specific detail page. Transition words such as “if” and “then” help clarify the logic flow. You must also create the corresponding XML templates (class_not_found and class_detail) to support this functionality.
Integrating AJAX for Real-Time Data Updates
To enhance user experience, you can integrate AJAX calls into your templates for real-time update of data without reloading pages. For instance, create a separate route to return JSON data:
@http.route('/odoodiscussions/get_classes', auth='public', type='json')
def get_classes(self, **kwargs):
classes = request.env['openacademy.class'].sudo().search([])
class_data = [{'id': cls.id, 'name': cls.name} for cls in classes]
return class_data
In your QWeb template, you can call this route using JavaScript to update class content dynamically. This technique boosts interactivity and makes your website feel modern and responsive.
Incorporating Custom CSS and JavaScript
To achieve a polished look and enhanced interactivity, include custom static files (CSS and JS) in your module. Add a file in your module’s static/src directory and reference it in the QWeb template:
<odoo>
<template id="assets_frontend" name="OpenAcademy Assets" inherit_id="website.assets_frontend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/od_openacademy_website/static/src/css/custom.css"/>
<script type="text/javascript" src="/od_openacademy_website/static/src/js/custom.js"></script>
</xpath>
</template>
</odoo>
This integration ensures that your website not only functions well but also looks appealing and operates smoothly on various devices.
Additional Topics and Next Steps
After you finish this tutorial, you can further expand your module’s capabilities by exploring the following topics:
- Security and Access Management:
Enhance security by defining user-specific access rights in their.model.access.csvfile and configuring controllers for authenticated sessions withauth='user'. - Multi-language Support:
Leverage Odoo’s internationalization features to support multiple languages. Customize your templates to render content in different languages based on user settings. - Version Control and Continuous Integration:
Use Git to manage changes in your Odoo modules. For example, refer to our update on GitHub for a sample commit that enhances module functionality:
Odoo Addons Commit. - Responsive Design Techniques:
Use modern CSS frameworks and JavaScript libraries to create responsive, mobile-friendly pages. Transition from static templates to dynamic, interactive designs that adjust seamlessly across devices.
Recap and Conclusion
In conclusion, we have covered a comprehensive guide on Odoo Controllers and Routes in this tutorial. You learned how to set up the development environment, create a basic controller, define routes, and design QWeb templates to display both static and dynamic data. Additionally, we explored advanced techniques such as dynamic URL parameters, AJAX integration, and custom asset management. Each section used clear, active language and logical transitions to break down complex concepts into small, manageable parts.
By consistently using keyphrases like “Odoo Controllers and Routes,” “Odoo website controller,” and “route configuration,” you have gained valuable insights into the inner workings of Odoo’s web framework. You now understand how to fetch data from models, render it with QWeb templates, and enhance user experience with dynamic content. Furthermore, you are equipped with troubleshooting strategies, best practices, and advanced customization techniques that will propel your Odoo development skills to the next level.
Conclusion
We encourage you to experiment with the code samples provided, and to read more about advanced topics in the Odoo Documentation. As you build more complex modules, remain consistent with your coding style and always aim for clear, maintainable code. In the future, you might extend this module by integrating more interactive features such as real-time notifications, custom form submissions, and user dashboards.
Ultimately, Odoo Controllers and Routes are vital tools in your development arsenal. They allow you to design intuitive web interfaces while maintaining a clear separation between application logic and presentation. As you continue developing, ensure you test every component and consult community resources and official documentation to stay updated on best practices.
Thank you for following along with this tutorial. We hope that by applying these techniques, you will create powerful and engaging websites on the Odoo platform. Happy coding, and remember to keep exploring and innovating with Odoo’s robust framework!
Appendix: Complete Code Overview
Below is the complete code for a basic module that demonstrates all concepts discussed.
Python Controller File (controllers/main.py)
from odoo import http
from odoo.http import request
import logging
_logger = logging.getLogger(__name__)
class OdooDiscussions(http.Controller):
@http.route('/odoodiscussions/classes', auth='public', website=True)
def display_classes(self, **kwargs):
_logger.info("display_classes called with kwargs: %s", kwargs)
# Query all class records from the openacademy.class model
classes = request.env['openacademy.class'].sudo().search([])
template = 'od_openacademy_website.odoodiscussions_classes'
return request.render(template, {'classes': classes})
@http.route('/odoodiscussions/classes/<int:class_id>', auth='public', website=True)
def display_class_detail(self, class_id, **kwargs):
_logger.info("display_class_detail called for class_id: %s", class_id)
class_record = request.env['openacademy.class'].sudo().browse(class_id)
if not class_record:
return request.render('od_openacademy_website.class_not_found', {})
return request.render('od_openacademy_website.class_detail', {'class': class_record})
QWeb Template File (views/template.xml)
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<template id="odoodiscussions_classes" name="Odoo discussions Classes">
<title>Odoo discussions</title>
<h3>Classes</h3>
<t t-if="classes and classes != []">
<ul>
<t t-foreach="classes" t-as="cls">
<li>
<strong><t t-esc="cls.name"/></strong>: <t t-esc="cls.description"/>
</li>
</t>
</ul>
</t>
<t t-else="">
<p>No classes available.</p>
</t>
</template>
<template id="class_not_found" name="Class Not Found">
<div class="alert alert-warning">
<p>The requested class does not exist.</p>
</div>
</template>
<template id="class_detail" name="Class Detail">
<h2><t t-esc="class.name"/></h2>
<p><t t-esc="class.description"/></p>
</template>
</odoo>
Model Definition File (models/openacademy.py)
from odoo import models, fields
class Class(models.Model):
_name = 'openacademy.class'
_description = 'Class'
name = fields.Char(string='Class Name', required=True)
description = fields.Text(string='Description')
Manifest File (__manifest__.py)
{
'name': 'Odoo OpenAcademy Website',
'summary': 'Display data using Odoo Controllers and Routes',
'description': 'This module demonstrates how to build and customize Odoo website controllers, define routes, and render QWeb templates to present dynamic data.',
'author': 'Your Name',
'depends': ['website'],
'data': [
'views/template.xml',
],
'installable': True,
'application': True,
}
By examining each code segment and following the explanations provided, you can recreate and extend the module in your own Odoo environment. Each step builds towards a deeper understanding of Odoo Controllers and Routes, giving you the tools to create highly interactive and user-friendly web applications.
Happy coding, and enjoy the journey into the world of Odoo development!
Discover more from teguhteja.id
Subscribe to get the latest posts sent to your email.



