Author: |
MONK Software |
License: |
LGPL-3 |
Branch: |
10.0-base_request_rest |
Repository: |
LeartS/rest-framework |
Dependencies: |
web |
Languages: |
Python (243, 69.0%),
and
reStructuredText (109, 31.0%) |
<h1 class="title">REST Controllers in Odoo</h1>
<a name="introduction"></a>
<h2>Introduction</h2>
<p>This module allows you to define REST controllers in Odoo.
Normally this is not possible, because Odoo assumes that all json requests
are JSON-RPC and does some "magic" stuff that doesn't let you return
the kind of responses usually returned by REST APIs.
With this module, not only you can workaround the JSON-RPC limitation,
but you get a lot of convenience methods to quickly and easily implement
REST APIs -- for example, by having recordset be converted automagically
to a JSON representation!</p>
<a name="usage"></a>
<h2>Usage</h2>
<a name="basic-usage"></a>
<h3>Basic usage</h3>
<p>You define REST controllers like normal odoo controllers,
you'll only need to use the
<code>odoo.addons.base_request_rest.http.restroute</code> decorator
(or <code>restroutemulti</code> or <code>restroutesingle</code>, see below) instead
of the standard <code>odoo.http.route</code> one.</p>
<p>For example:</p>
<pre>
<code>from odoo.addons.base_request_rest.http import restroute
@restroute('/api/partners')
def list_partners(self, **params):
return request.env['res.partner'].search_read(
[], ['name', 'street'], limit=2)</code>
</pre>
<p>If you now go to <code>/api/partners</code>, you'll get a JSON response
(i.e. with the appropriate HTTP headers set) with
the following body (for example):</p>
<pre>
<code>{
"status": "success",
"data": [
{"street": "Main street, 2", "id": 123, "name": "A big company"},
{"street": false, "id": 124, "name": "A BIGGER company"}
]
}</code>
</pre>
<p>The dict returned by <code>search_read</code> has been automatically converted to its
JSON representation, and the JSON response data has been automatically wrapped
in a response object according to the <a class="reference external" href="https://labs.omniti.com/labs/jsend">jsend specification</a></p>
<p>You can optionally disable the jsend response format by setting
<code>USE_JSEND = False</code>:</p>
<pre>
<code>from odoo.addons.base_request_rest import settings
settings.USE_JSEND = False</code>
</pre>
<a name="automatic-return-value-conversion"></a>
<h3>Automatic return value conversion</h3>
<p>The dict is only one of the supported return types that are automatically
converted to appropriate HTTP responses. In fact, from your controllers
you can return:</p>
<ul class="simple">
<li>An instances of <code>http.Response</code>, which will be returned as-is</li>
<li>An integer, which will be used as the response status code (no body)</li>
<li>Any base type, list, dict or tuple (let's call these <em>JSON-serializable objects</em>):
will be serialized using <code>json.dumps</code> and returned with status code 200</li>
<li>A tuple (int, <em>JSON-serializable object</em>): like above, with an explicit status code</li>
<li>Last, but definitely not least.. return directly a recordset that inherits
from <code>rest.mixin</code> ! Keep reading to see how...</li>
</ul>
<a name="rest-mixin"></a>
<h2>rest.mixin</h2>
<p><code>rest.mixin</code> is an abstract model that you can make other models inherit in
order to gain some super convenient rest functionalities:</p>
<ul class="simple">
<li>Easy to define fields to export with name mapping: you only need to declare
a <code>_rest_fields_map</code> attribute in the class that maps odoo fields
to api keys in the returned JSON</li>
<li>Automatic JSON serialization: return recordset directly from your controller,
it will be serialized to JSON automatically in the response.</li>
<li>Customizable (de)serialization: rest.mixin provides the <code>to_json</code> and
<code>from_json</code> methods that you can override to completely customize how
records are serialized.</li>
</ul>
<p>For example, using <code>mixin</code>, this is all you have to do to create
a read-only API that exposes your projects and projects' tasks:</p>
<pre>
<code>class RESTProjectProject(models.Model):
_name = 'project.project'
_inherit = ['project.project', 'rest.mixin']
_rest_fields_map = {
'id': 'id',
'name': 'name',
'user_id': 'projectManager',
}
class RESTProjectProject(models.Model):
_name = 'project.task'
_inherit = ['project.task', 'rest.mixin']
@restroutemulti('/projects')
def list_projects(self):
return request.env['project.project'].search([])
@restroutesingle('/projects/<model("project.project"):project>')
def get_project(self, project):
return project
@restroutemulti('/projects/<model("project.project"):project>/tasks')
def list_project_tasks(self, project):
return project.task_ids</code>
</pre>
<a name="notes"></a>
<h2>Notes</h2>
<p>By deafult the controllers defined using the restroute* decorators are prefixed
with <code>/rest</code>. So, for example, @restroutemulti('/projects') will be
published under <code>/rest/projects</code>. You can change this default prefix by
setting the related variable before importing your controllers; for
example write the following in your module's main __init__.py:</p>
<pre>
<code>from odoo.addons.base_request_rest import settings
settings.API_PREFIX = '/api/v1'</code>
</pre>
<a name="credits"></a>
<h2>Credits</h2>
<a name="contributors"></a>
<h3>Contributors</h3>
<ul class="simple">
<li>Leonardo Donelli (LeartS) <<a class="reference external" href="mailto:donelli@monksoftware.it">donelli@monksoftware.it</a>></li>
</ul>
<a name="funders"></a>
<h3>Funders</h3>
<p>The development of this module has been financially supported by:</p>
<ul class="simple">
<li>MONK Software</li>
</ul>