URLs and routing
Controller methods are associated with_routes_via theroute()
decorator which takes a routing string and a number of attributes to customise its behavior or security.
We've seen a "literal" routing string, which matches a URL section exactly, but routing strings can also useconverter patternswhich match bits of URLs and make those available as local variables. For instance we can create a new controller method which takes a bit of URL and prints it out:
academy/controllers.py
'teachers': Teachers.search([])
})
@http.route('/academy/<name>/', auth='public', website=True)
def teacher(self, name):
return '<h1>{}</h1>'.format(name)
# @http.route('/academy/academy/objects/', auth='public')
# def list(self, **kw):
# return http.request.render('academy.listing', {
restart Odoo, accesshttp://localhost:8069/academy/Alice/andhttp://localhost:8069/academy/Bob/and see the difference.
As the name indicates,converter patternsdon't just do extraction, they also dovalidation_and_conversion, so we can change the new controller to only accept integers:
academy/controllers.py
'teachers': Teachers.search([])
})
@http.route('/academy/<int:id>/', auth='public', website=True)
def teacher(self, id):
return '<h1>{} ({})</h1>'.format(id, type(id).__name__)
# @http.route('/academy/academy/objects/', auth='public')
Restart Odoo, accesshttp://localhost:8069/academy/2, note how the old value was a string, but the new one was converted to an integers. Try accessinghttp://localhost:8069/academy/Carol/and note that the page was not found: since "Carol" is not an integer, the route was ignored and no route could be found.
Odoo provides an additional converter calledmodel
which provides records directly when given their id. Let's use this to create a generic page for teacher biographies:
academy/controllers.py
'teachers': Teachers.search([])
})
@http.route('/academy/<model("academy.teachers"):teacher>/', auth='public', website=True)
def teacher(self, teacher):
return http.request.render('academy.biography', {
'person': teacher
})
# @http.route('/academy/academy/objects/', auth='public')
academy/templates.xml
</div>
</t>
</template>
<template id="biography">
<t t-call="website.layout">
<t t-set="title">Academy</t>
<div class="oe_structure"/>
<div class="oe_structure">
<div class="container">
<p><t t-esc="person.id"/> <t t-esc="person.name"/></p>
</div>
</div>
<div class="oe_structure"/>
</t>
</template>
<!-- <template id="object"> -->
<!-- <h1><t t-esc="object.display_name"/></h1> -->
<!-- <dl> -->
then change the list of model to link to our new controller:
academy/templates.xml
<div class="oe_structure">
<div class="container">
<t t-foreach="teachers" t-as="teacher">
<p><a t-attf-href="/academy/{{ slug(teacher) }}">
<t t-esc="teacher.name"/></a>
</p>
</t>
</div>
</div>
<div class="oe_structure"/>
<div class="oe_structure">
<div class="container">
<h3><t t-esc="person.name"/></h3>
</div>
</div>
<div class="oe_structure"/>
Restart Odoo and upgrade the module, then you can visit each teacher's page. As an exercise, try adding blocks to a teacher's page to write a biography, then go to another teacher's page and so forth. You will discover, that your biography is shared between all teachers, because blocks are added to the template, and the _biography _template is shared between all teachers, when one page is edited they're all edited at the same time.