Odoo's treatment of the functions' return values is determined by the type argument of the route decorator. For type='http', we usually want to deliver some HTML, so the first function simply returns a string containing it. An alternative is to use request.make_response(), which gives you control over the headers to send in the response. So, to indicate when our page was last updated, we might change the last line in books() to the following code:
return request.make_response( html_result, [ ('Last-modified', email.utils.formatdate( ( fields.Datetime.from_string( request.env['library.book'].sudo() .search([], order='write_date desc', limit=1) .write_date) - datetime.datetime(1970, 1, 1) ).total_seconds(), usegmt=True)), ])
This code sends a Last-modified header along with the HTML we generated, telling the browser when the list was modified for the last time. We can extract this information from the write_date field of the library.book model.
In order for the preceding snippet to work, you'll have to add some imports on the top of the file, as follows:
import email import datetime from odoo import fields
You can also create a Response object of werkzeug manually and return that, but there's little to gain for the effort.
This will give you localization for free and will make your code better by separating business logic from the presentation layer. Also, templates provide you with functions to escape data before outputting HTML. The preceding code is vulnerable to cross-site scripting attacks (if a user manages to slip a script tag into the book name, for example).
For a JSON request, simply return the data structure you want to hand over to the client; Odoo takes care of serialization. For this to work, you should restrict yourself to data types that are JSON serializable, which are roughly dictionaries, lists, strings, floats, and integers.