Author: |
ACSONE SA/NV,Odoo Community Association (OCA) |
License: |
LGPL-3 |
Branch: |
14.0-add-pydantic |
Repository: |
acsone/rest-framework |
Languages: |
HTML (432, 36.3%),
Python (682, 57.4%),
and
reStructuredText (75, 6.3%) |
Other branches: |
13.0-backport-base-rest-pydantic,
14.0,
14.0-base-rest-pydantic-lmi,
14.0-deprecated-implicit-rest-method,
14.0-fdl_master,
14.0-fix-response-processing,
14.0-moz_master,
15.0,
16.0,
16.0-fastapi,
16.0-mfr_fix_base_rest_missing_argument,
and
16.0-upgrade-pre-commit |
Other repositories: |
Change2improve/rest-framework,
Digital5-Odoo/rest-framework,
Gabinete-Digital/rest-framework,
OCA/rest-framework,
SeuMarco/rest-framework,
akretion/rest-framework,
coopiteasy/rest-framework,
gastonfeng/rest-framework,
and
ursais/rest-framework |
<h1 class="title">Pydantic</h1>
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/rest-framework/tree/14.0/pydantic"><img alt="OCA/rest-framework" src="https://img.shields.io/badge/github-OCA%2Frest--framework-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/rest-framework-14-0/rest-framework-14-0-pydantic"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/271/14.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This addon allows you to define inheritable <a class="reference external" href="https://pydantic-docs.helpmanual.io/">Pydantic classes</a>.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="id1">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="id2">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<a name="usage"></a>
<h2><a class="toc-backref" href="#id1">Usage</a></h2>
<p>To define your own pydantic model you just need to create a class that inherits from
<code>odoo.addons.pydantic.models.BaseModel</code> or a subclass of.</p>
<pre>
<code lang="python">from odoo.addons.pydantic.models import BaseModel
from pydantic import Field
class PartnerShortInfo(BaseModel):
id: str
name: str
class PartnerInfo(BaseModel):
street: str
street2: str = None
zip_code: str = None
city: str
phone: str = None
is_componay : bool = Field(None)</code>
</pre>
<p>In the preceding code, 2 new models are created, one for each class. If you
want to extend an existing model, you must pass the extended pydantic model
trough the <cite>extends</cite> parameter on class declaration.</p>
<pre>
<code lang="python">class Coordinate(models.BaseModel):
lat = 0.1
lng = 10.1
class PartnerInfoWithCoordintate(PartnerInfo, extends=PartnerInfo):
coordinate: Coordinate = None</code>
</pre>
<p><cite>PartnerInfoWithCoordintate</cite> extends <cite>PartnerInfo</cite>. IOW, Base class are now the
same and define the same fields and methods. They can be used indifferently into
the code. All the logic will be provided by the aggregated class.</p>
<pre>
<code lang="python">partner1 = PartnerInfo.construct()
partner2 = PartnerInfoWithCoordintate.construct()
assert partner1.__class__ == partner2.__class__
assert PartnerInfo.schema() == PartnerInfoWithCoordinate.schema()</code>
</pre>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Since validation occurs on instance creation, it's important to avoid to
create an instance of a Pydantic class by usign the normal instance
constructor <cite>partner = PartnerInfo(..)</cite>. In such a case, if the class is
extended by an other addon and a required field is added, this code will
no more work. It's therefore a good practice to use the <cite>construct()</cite> class
method to create a pydantic instance.</p>
</div>
<div class="admonition caution">
<p class="first admonition-title">Caution!</p>
<p class="last">Adding required fields to an existing data structure into an extension
addon violates the <a class="reference external" href="https://en.wikipedia.org/wiki/Liskov_substitution_principle">Liskov substitution principle</a> and should generally
be avoided. This is certainly forbidden in requests data structures.
When extending response data structures this could be useful to document
new fields that are guaranteed to be present when extension addons are
installed.</p>
</div>
<p>In contrast to Odoo, access to a Pydantic class is not done through a specific
registry. To use a Pydantic class, you just have to import it in your module
and write your code like in any other python application.</p>
<pre>
<code lang="python">from odoo.addons.my_addons.datamodels import PartnerInfo
from odoo import models
class ResPartner(models.Basemodel):
_inherit = "res.partner"
def to_json(self):
return [i._to_partner_info().json() for i in self]
def _to_partner_info(self):
self.ensure_one()
pInfo = PartnerInfo.construct(id=self.id, name=self.name, street=self.street, city=self.city)
return pInfo</code>
</pre>
<p>To support pydantic models that map to Odoo models, Pydantic model instances can
be created from arbitrary odoo model instances by mapping fields from odoo
models to fields defined by the pydantic model. To ease the mapping, the addon
provide a utility class <cite>odoo.addons.pydantic.utils.GenericOdooGetter</cite>.</p>
<pre>
<code lang="python">import pydantic
from odoo.addons.pydantic import models, utils
class Group(models.BaseModel):
name: str
class Config:
orm_mode = True
getter_dict = utils.GenericOdooGetter
class UserInfo(models.BaseModel):
name: str
groups: List[Group] = pydantic.Field(alias="groups_id")
class Config:
orm_mode = True
getter_dict = utils.GenericOdooGetter
user = self.env.user
user_info = UserInfo.from_orm(user)</code>
</pre>
<p>See the official <a class="reference external" href="https://pydantic-docs.helpmanual.io/">Pydantic documentation</a> to discover all the available functionalities.</p>
<a name="known-issues-roadmap"></a>
<h2><a class="toc-backref" href="#id2">Known issues / Roadmap</a></h2>
<p>The <a class="reference external" href="https://github.com/OCA/rest-framework/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement+label%3Apydantic">roadmap</a>
and <a class="reference external" href="https://github.com/OCA/rest-framework/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Apydantic">known issues</a> can
be found on GitHub.</p>
<a name="bug-tracker"></a>
<h2><a class="toc-backref" href="#id3">Bug Tracker</a></h2>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/rest-framework/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/rest-framework/issues/new?body=module:%20pydantic%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
<a name="credits"></a>
<h2><a class="toc-backref" href="#id4">Credits</a></h2>
<a name="authors"></a>
<h3><a class="toc-backref" href="#id5">Authors</a></h3>
<ul class="simple">
<li>ACSONE SA/NV</li>
</ul>
<a name="contributors"></a>
<h3><a class="toc-backref" href="#id6">Contributors</a></h3>
<ul class="simple">
<li>Laurent Mignon <<a class="reference external" href="mailto:laurent.mignon@acsone.eu">laurent.mignon@acsone.eu</a>></li>
</ul>
<a name="maintainers"></a>
<h3><a class="toc-backref" href="#id7">Maintainers</a></h3>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external" href="https://github.com/lmignon"><img alt="lmignon" src="https://github.com/lmignon.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/rest-framework/tree/14.0/pydantic">OCA/rest-framework</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>