Are you looking to create custom routes in Odoo Website that can handle model records as parameters using the slug function? In this comprehensive tutorial, I’ll walk you through the process of creating routes in Odoo Website that use model records as parameters. This powerful technique allows you to build SEO-friendly URLs and create more intuitive navigation paths for your Odoo applications.
Why Use Slug Parameters in Odoo Routes?
When developing custom websites with Odoo, you often need to create routes that link to specific model records. For instance, you might want to display a product category page with a URL like /category/office-supplies instead of /category/42. Using the slug function provides several important benefits:
- SEO-friendly URLs: Search engines prefer descriptive URLs over ones filled with numbers and IDs.
- Improved user experience: Users can better understand where a link will take them.
- More memorable links: Text-based URLs are easier to remember than numeric IDs.
- Maintainable code: Your routes become more meaningful to developers maintaining the code.
Let’s dive into how to implement this in your Odoo website.
Understanding the Basics: Routes in Odoo Website
Before we get into creating routes with slug parameters, let’s first understand how basic routes work in Odoo.
In Odoo’s website module, routes are defined using Python decorators. The most common decorator is @http.route(), which allows you to specify:
- The URL pattern
- The HTTP methods allowed (GET, POST, etc.)
- Authentication requirements
- And more
Here’s a simple example of a basic route:
@http.route('/my-route', type='http', auth='public', website=True)
def my_route_function(self):
return request.render('module_name.template_id')
This creates a route at /my-route that renders a specific template when accessed.
Getting Started with Slug Parameters
In our previous example, we saw how to create routes with specific parameters. Now, let’s explore how to use model records as parameters using the slug function.
What is the Slug Function?
The slug() function in Odoo converts a record name and ID into a URL-friendly string. For example, if you have a product category named “Office Supplies” with ID 42, slug(category) might return something like office-supplies-42.
Setting Up Our Project
First, let’s create a route that accepts a model record as a parameter. We’ll build on the example from the context:
@http.route('/category/<model("product.category"):category>', type='http', auth='public', website=True)
def product_category(self, category):
# Display information about the category
print("ID:", category.id)
print("Name:", category.name)
return request.render('module_name.product_category_template', {
'category': category
})
In this route, <model("product.category"):category> tells Odoo to:
- Look for a
product.categoryrecord - That matches the slug provided in the URL
- And pass it to our function as the
categoryparameter
Handling Permissions for Public Access
One common issue when creating routes with model parameters is access rights. If you’re creating a public-facing website, you need to ensure that public users have read access to the models you’re using in your routes.
Adding Access Rights
To fix permission issues, you need to grant read access to the specific model for public users. In our example, we need to ensure public users can read product.category records.
Create or modify a security CSV file in your module:
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_product_category_public,product.category.public,model_product_category,base.group_public,1,0,0,0
This grants read-only access (perm_read=1) to the public user group for the product.category model.
Handling Errors Gracefully
Another important aspect to consider is error handling. What happens if a user tries to access a category that doesn’t exist? By default, Odoo will return a 500 error, which is not user-friendly.
Let’s modify our approach to handle errors more gracefully by extending the slug function behavior. We’ll create a custom implementation that redirects to a 404 page instead of showing a 500 error when a record doesn’t exist.
Create a new file named custom_slug.py in your module:
from odoo import models
from odoo.http import request
from odoo.addons.http_routing.models.ir_http import slug as original_slug
class CustomSlug(models.AbstractModel):
_inherit = 'ir.http'
def slug(self, record):
try:
return original_slug(record)
except ValueError:
# Log the error for debugging
print("Custom error in slug method with record:", record)
# Return empty string to trigger a 404 redirect
return ""
Then, update your module’s __init__.py to import this file.
Creating Links to Our Custom Routes
Now that we have our route set up, let’s create links that use it. In your templates, you can create links using the slug function:
<a t-att-href="'/category/' + slug(category)">
<t t-esc="category.name"/>
</a>
This will generate a link like /category/office-supplies-42 that, when clicked, will route to our product_category function with the appropriate category loaded.
Building a Complete Example
Let’s put everything together in a complete example. We’ll create a module with:
- Custom routes for viewing product categories
- Templates for displaying category information
- Proper security settings
- Error handling for invalid slugs
Module Structure
my_module/
├── __init__.py
├── __manifest__.py
├── controllers/
│ ├── __init__.py
│ └── main.py
├── models/
│ ├── __init__.py
│ └── custom_slug.py
├── security/
│ └── ir.model.access.csv
└── views/
└── templates.xml
Main Controller (controllers/main.py)
from odoo import http
from odoo.http import request
from odoo.addons.http_routing.models.ir_http import slug
class CategoryController(http.Controller):
@http.route('/categories', type='http', auth='public', website=True)
def categories_list(self):
# Display a list of all categories
categories = request.env['product.category'].sudo().search([])
return request.render('my_module.categories_list_template', {
'categories': categories
})
@http.route('/category/<model("product.category"):category>', type='http', auth='public', website=True)
def product_category(self, category):
# Display information about the specific category
print("ID:", category.id)
print("Name:", category.name)
return request.render('my_module.product_category_template', {
'category': category
})
Templates (views/templates.xml)
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Template for listing all categories -->
<template id="categories_list_template" name="Categories List">
<t t-call="website.layout">
<div class="container">
<h1>Product Categories</h1>
<div class="row">
<div class="col-md-12">
<ul class="list-group">
<t t-foreach="categories" t-as="category">
<li class="list-group-item">
<a t-att-href="'/category/' + slug(category)">
<t t-esc="category.name"/>
</a>
</li>
</t>
</ul>
</div>
</div>
</div>
</t>
</template>
<!-- Template for displaying a specific category -->
<template id="product_category_template" name="Product Category">
<t t-call="website.layout">
<div class="container">
<h1><t t-esc="category.name"/></h1>
<div class="row">
<div class="col-md-12">
<p>Category ID: <t t-esc="category.id"/></p>
<h2>Products in this category</h2>
<ul class="list-group">
<t t-foreach="category.product_tmpl_ids" t-as="product">
<li class="list-group-item">
<t t-esc="product.name"/>
</li>
</t>
</ul>
</div>
</div>
</div>
</t>
</template>
</odoo>
Security Settings (security/ir.model.access.csv)
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_product_category_public,product.category.public,product.model_product_category,base.group_public,1,0,0,0
Advanced Techniques for Slug Parameters
Now that we’ve covered the basics, let’s explore some advanced techniques for working with slug parameters in Odoo.
Multiple Parameters in Routes
You can combine multiple parameters in your routes, including both model records and primitive types:
@http.route('/category/<model("product.category"):category>/page/<int:page>', type='http', auth='public', website=True)
def product_category_paged(self, category, page=1):
# Paginated display of products in a category
products_per_page = 10
products = request.env['product.template'].sudo().search([
('categ_id', '=', category.id)
], limit=products_per_page, offset=(page-1)*products_per_page)
total_products = request.env['product.template'].sudo().search_count([
('categ_id', '=', category.id)
])
total_pages = (total_products + products_per_page - 1) // products_per_page
return request.render('my_module.product_category_paged_template', {
'category': category,
'products': products,
'page': page,
'total_pages': total_pages
})
Nested Model Relationships
Sometimes you need to navigate through related models in your routes. For example, you might want to display all products of a specific category and brand:
@http.route('/category/<model("product.category"):category>/brand/<model("res.partner"):brand>', type='http', auth='public', website=True)
def category_brand_products(self, category, brand):
products = request.env['product.template'].sudo().search([
('categ_id', '=', category.id),
('manufacturer', '=', brand.id)
])
return request.render('my_module.category_brand_products_template', {
'category': category,
'brand': brand,
'products': products
})
Using Slugs for SEO Optimization
The slug function is not just for routing; it’s a powerful tool for SEO optimization. You can use it to generate SEO-friendly URLs for your content.
For example, if you’re building a blog module, you might use slugs to create URLs like /blog/how-to-optimize-your-odoo-website instead of /blog/post/42.
@http.route('/blog/<model("blog.post"):post>', type='http', auth='public', website=True)
def blog_post(self, post):
return request.render('my_module.blog_post_template', {
'post': post
})
Troubleshooting Common Issues
When working with slug parameters in Odoo routes, you might encounter some common issues. Let’s address them:
500 Server Error
If you get a 500 server error when accessing your route, it could be due to:
- Access rights issues: Ensure public users have read access to the model.
- Non-existent record: The slug might be referring to a record that doesn’t exist.
- Custom errors in the template: Check your template for possible errors.
Our custom slug implementation helps handle the non-existent record issue by redirecting to a 404 page.
Performance Considerations
When using model parameters in routes, be mindful of performance implications:
- Database queries: Each route access will query the database to fetch the record.
- Cache utilization: Consider using Odoo’s caching mechanisms for frequently accessed routes.
- Security checks: Odoo performs access rights checks for each record, which adds overhead.
URL Conflicts
Be careful with route patterns to avoid conflicts. For example, if you have:
@http.route('/category/<string:name>', type='http', auth='public', website=True)
def category_by_name(self, name):
# ...
@http.route('/category/<model("product.category"):category>', type='http', auth='public', website=True)
def product_category(self, category):
# ...
Odoo might have trouble distinguishing between these routes. Always design your URL structure carefully to avoid conflicts.
Best Practices for Odoo Website Routes
Let’s wrap up with some best practices for creating and managing routes in Odoo websites:
1. Consistent URL Structure
Maintain a consistent URL structure across your website. For example:
/model/record-slugfor individual records/model/record-slug/related-modelfor related records/model/record-slug/actionfor actions on records
2. Proper Security Management
Always consider who should have access to your routes:
- Use
auth='public'only when the route should be accessible to everyone - Use
auth='user'when authentication is required - Set up proper record rules and access rights
3. Error Handling
Implement proper error handling to provide a good user experience:
- Redirect to a 404 page for non-existent records
- Provide clear error messages
- Log errors for debugging purposes
4. Caching Considerations
For high-traffic websites, consider implementing caching:
@http.route('/category/<model("product.category"):category>', type='http', auth='public', website=True, website_published=True)
def product_category(self, category):
# Add cache headers for browsers
response = request.render('my_module.product_category_template', {
'category': category
})
response.headers['Cache-Control'] = 'public, max-age=300'
return response
5. URL Canonicalization
Ensure that each resource has a single canonical URL to avoid SEO penalties:
@http.route([
'/category/<model("product.category"):category>',
'/categories/<model("product.category"):category>', # Alternative URL
], type='http', auth='public', website=True)
def product_category(self, category):
# Redirect alternative URLs to the canonical one
if request.httprequest.path.startswith('/categories/'):
return request.redirect('/category/' + slug(category), 301)
return request.render('my_module.product_category_template', {
'category': category
})
Conclusion: Leveraging the Power of Slug Parameters in Odoo Routes
In this comprehensive guide, we’ve explored how to create routes in Odoo that use the slug function to work with model records as parameters. By implementing these techniques, you can create more user-friendly and SEO-optimized URLs for your Odoo website.
We’ve covered everything from basic route definition to advanced techniques like custom slug handling, multiple parameters, and nested relationships. We’ve also addressed common issues and provided best practices for route management in Odoo.
By mastering these concepts, you’ll be able to create more sophisticated and user-friendly web applications with Odoo. Remember that well-designed URLs not only help with SEO but also improve the overall user experience of your website.
For more information about Odoo website development, check out the official Odoo documentation or explore the Odoo Community Association resources.
What route will you build next with your new slug parameter skills? The possibilities are endless!
Discover more from teguhteja.id
Subscribe to get the latest posts sent to your email.


Pingback: Awesome Odoo AI Website Copy: 5 Steps