In Odoo 19, controllers serve as the bridge between the web client (browser, mobile app, or API consumer) and the server-side logic of Odoo. They define how HTTP requests are handled, enabling developers to expose custom endpoints for both internal and external interactions.
Controllers in Odoo are defined using the @http.route decorator and can respond to different types of HTTP requests, such as GET, POST, PUT, and DELETE.
This documentation covers the basic types of controllers used in Odoo 19:
1. Basic HTTP Controller
This is the most common type of controller, the HTTP controller. Used for rendering HTML pages. They are typically used for public-facing website pages, such as a contact form, a product landing page, or a custom "About Us" page
Key Parameters:
- route: The URL path to the controller method.
- type='http': Indicates a standard HTTP route.
- auth: Specifies the authentication requirement.
- public: Accessible to anyone, including non-logged-in visitors.
- user: Requires a logged-in user.
- bearer: can use an API token instead of logging in, still uses your user rights.
- none: For internal use; rarely used for custom modules.
- website: True if the page should use the Odoo website's theme and header/footer.
Example:
from odoo import http
class MyWebsiteController(http.Controller):
@http.route('/hello', type='http', auth='public', website=True)
def hello_world(self, **kwargs):
return "<h1>Hello, World!</h1>"
2. JSON-RPC Controller
In Odoo, JSON-RPC is a lightweight way for the frontend to communicate with the backend using JSON. Controllers that handle JSON-RPC allow JavaScript to call Python methods asynchronously, making it ideal for tasks like loading data, submitting forms, or updating the UI without refreshing the whole page.
These controllers respond with JSON data, which is commonly used for AJAX-style interactions between the frontend and backend.
Key Parameter:
- type='jsonrpc': Automatically handles JSON request parsing and response serialization.
Example:
from odoo import http
from odoo.http import request
class MyJsonController(http.Controller):
@http.route('/my/test/json', type='jsonrpc', auth='user')
def my_json_method(self, **kwargs):
return {'message': 'JSON response'}
3. REST Controller
In Odoo, a REST controller is a Python controller that exposes backend methods through standard HTTP routes, usually responding with JSON. It allows external systems or frontend apps to interact with Odoo using RESTful APIs, supporting operations like GET, POST, PUT, and DELETE. REST controllers are commonly used for integrations, mobile apps, or any situation where you need to access Odoo data from outside the web client.
Key Parameter:
- methods=['GET', 'POST', 'PUT', 'DELETE']
GET > Fetch or read data from the server.
POST > Create new records or send data to the server.
PUT > Update existing records.
DELETE > Remove records from the database.
Example:
from odoo import http
from odoo.http import request
class SimplePartnerController(http.Controller):
"""Simple REST API for res.partner"""
@http.route('/api/partners', type='jsonrpc', auth='public', methods=['GET'])
def get_partners(self):
"""Get list of partners"""
partners = request.env['res.partner'].sudo().search_read(
[], ['id', 'name'], limit=50
)
return {
'status': 'success',
'data': partners
}
@http.route('/api/partners', type='jsonrpc', auth='public', methods=['POST'])
def create_partner(self):
"""Create a new partner"""
data = request.get_json_data()
if not data.get('name'):
return {'status': 'error', 'message': 'Name is required'}
partner = request.env['res.partner'].sudo().create({
'name': data.get('name'),
'email': data.get('email')
})
return {
'status': 'success',
'data': {'id': partner.id, 'name': partner.name}
}
Tip: Use type='http' and csrf=False for REST APIs that will be called externally.
4. Authenticated Controller
An authenticated controller in Odoo is a Python controller that requires the user to be logged in before accessing its routes. This ensures that only authorized users can interact with certain backend logic or data. You specify authentication using the auth parameter in the @http.route decorator.
Set auth='user' or auth='employee' to restrict access.
Example:
from odoo import http
from odoo.http import request
class AuthenticatedHello(http.Controller):
@http.route('/auth/hello', type='http', auth='user', website=True)
def hello_user(self):
user = request.env.user
return f"<h1>Hello, {user.name}! You are logged in.</h1>"
- auth='user': Requires any authenticated user.
- auth=’bearer’: The route allows authentication via an API token sent in the request header:The request runs with the permissions of the user who owns that API token.If the token is missing, it falls back to a normal logged-in session (like auth='user').
- Website = True: This allows Odoo to differentiate between web session users and external API clients.
5. Public Controller
A public controller in Odoo is a Python controller whose routes can be accessed by anyone, without requiring the user to be logged in. These controllers are commonly used to expose data or services to the public, such as APIs, website pages, or webhooks.
Set auth='public' to make the route open to all users.Public controllers can handle JSON or HTTP requests and often use sudo() to bypass access restrictions for reading data.
Example:
from odoo import http
class HelloPublic(http.Controller):
@http.route('/hello', type='http', auth='public', website=True)
def hello_world(self):
return "<h1>Hello, this is a public page!</h1>"
- Be cautious with public controllers when exposing sensitive data.
Best Practice: Always use the most restrictive authentication necessary. Use public for public-facing content and user for anything requiring user data or security.
CSRF in Odoo
CSRF (Cross-Site Request Forgery) is a security feature in Odoo that prevents unauthorized actions from malicious sites by verifying a unique token with every request.
- Enabled by default for most controllers (type='http' or type='jsonrpc').
- Disable it with csrf = False only when handling external requests (e.g., mobile apps, third-party webhooks) that cannot send a CSRF token.
6. API Versioning in Controllers
API versioning is a best practice that helps manage changes and maintain backward compatibility in your Odoo REST controllers. By including a version number in your API route (e.g., /api/v1/partners), you can release updates or new features without breaking existing integrations that rely on the old version.
Example:
from odoo import http
class ApiV1Controller(http.Controller):
@http.route('/api/v1/data', type='jsonrpc', auth='public')
def api_v1(self, **kwargs):
return {"version": "v1", "data": "Sample data"}
class ApiV2Controller(http.Controller):
@http.route('/api/v2/data', type='jsonrpc', auth='public')
def api_v2(self, **kwargs):
return {"version": "v2", "data": "Improved data"}
Versioning allows developers to make incremental improvements, deprecate old endpoints gracefully, and ensure that mobile apps or external systems continue to function even as your Odoo backend evolves.
Tip: Always include the version in the URL path rather than in headers for clarity and easier routing.
Conclusions
In Odoo 19, controllers are a powerful way to connect your backend with the outside world—whether you're serving pages to website visitors, handling requests from mobile apps, or integrating with other systems. They allow you to create custom endpoints for sending or receiving data, or even building full APIs. As you set them up, it’s important to keep things secure by managing authentication properly, handling CSRF protection, and versioning your APIs when needed. Following these practices helps keep your Odoo applications flexible, secure, and easier to manage in the long run.
To read more about How to Override an Existing Controller in Odoo 18, refer to our blog How to Override an Existing Controller in Odoo 18.