KEMBAR78
Odoo - Backend modules in v8 | PDF
Backend Modules in V8
Raphael Collet (rco@odoo.com)
Agenda
Architecture of Odoo
Module Open Academy
·
·
Architecture of Odoo
Architecture of Odoo
Three-tier client/server/database
Web client in Javascript
Server and backend modules in Python
MVC framework
·
·
·
·
Module Open Academy
The Module
Manage courses, sessions, and subscriptions
Learn
Structure of a module
Definition of data models
Definition of views and menus
·
·
·
·
·
Structure of a Module
An Odoo module is
a python module (data models), with
a manifest file,
XML and CSV data files (base data, views, menus),
frontend resources (Javascript, CSS).
·
·
·
·
The Open Academy Module
The manifest file __odoo__.py:
{{
'name':: 'Open Academy',,
'version':: '1.0',,
'category':: 'Tools',,
'summary':: 'Courses, Sessions, Subscriptions',,
'description':: "...",,
'depends' :: [['base'],],
'data' :: [['view/menu.xml'],],
'images':: [],[],
'demo':: [],[],
'application':: True,,
}}
The Course Model
A model and its fields are defined in a Python class:
fromfrom odoo importimport Model,, fields
classclass Course((Model):):
_name == 'openacademy.course'
name == fields..Char((string=='Title',, required==True))
description == fields..Text()()
The Menu as XML data
<?xml version="1.0" encoding="UTF-8"?>
<openerp><openerp>
<data><data>
<menuitem<menuitem name="Open Academy" id="menu_root" sequence="110"/>/>
<menuitem<menuitem name="General" id="menu_general" parent="menu_root"/>/>
<record<record model="ir.actions.act_window" id="action_courses">>
<field<field name="name">>Courses</field></field>
<field<field name="res_model">>openacademy.course</field></field>
<field<field name="view_mode">>tree,form</field></field>
</record></record>
<menuitem<menuitem name="Courses" id="menu_courses" parent="menu_general"
sequence="1" action="action_courses"/>/>
</data></data>
</openerp></openerp>
Let's add a Form View
<record<record model="ir.ui.view" id="course_form">>
<field<field name="name">>course form view</field></field>
<field<field name="model">>openacademy.course</field></field>
<field<field name="arch" type="xml">>
<form<form string="Course" version="7.0">>
<sheet><sheet>
<h1><h1>
<field<field name="name" placeholder="Course Title"/>/>
</h1></h1>
<notebook><notebook>
<page<page string="Description">>
<field<field name="description"/>/>
</page></page>
</notebook></notebook>
</sheet></sheet>
</form></form>
</field></field>
</record></record>
The Session Model
classclass Session((Model):):
_name == 'openacademy.session'
name == fields..Char((required==True))
start_date == fields..Date()()
duration == fields..Integer((help=="Duration in days"))
seats == fields..Integer((string=="Number of Seats"))
Relational Fields
Let us link sessions to courses and instructors:
classclass Session((Model):):
_name == 'openacademy.session'
......
course == fields..Many2one(('openacademy.course',, required==True))
instructor == fields..Many2one(('res.partner'))
Relational Fields
Let us back-link courses and sessions:
classclass Course((Model):):
_name == 'openacademy.course'
......
responsible == fields..Many2one(('res.users'))
sessions == fields..One2many(('openacademy.session',, 'course'))
Relational Fields
Let us link sessions to partners for attendee subscription:
classclass Session((Model):):
_name == 'openacademy.session'
......
attendees == fields..Many2many(('res.partner'))
Computed Fields
The value of those fields is computed:
classclass Session((Model):):
_name == 'openacademy.session'
......
taken_seats == fields..Float((compute=='_compute_taken_seats'))
@api.one@api.one
@api.depends@api.depends(('attendees',, 'seats'))
defdef _compute_taken_seats((self):):
ifif self..seats::
self..taken_seats == 100.0100.0 ** len((self..attendees)) // self..seats
elseelse::
self..taken_seats == 0.00.0
About self
Model instances are recordsetsrecordsets.
A recordset is an hybrid concept:
collection of records
record
forfor session inin self::
printprint session..name
printprint session..course..name
assertassert self..name ==== self[[00]]..name
·
·
Feedback with "Onchange"
Methods
Modify form values when some field is filled in:
classclass Session((Model):):
_name == 'openacademy.session'
......
@api.onchange@api.onchange(('course'))
defdef _onchange_course((self):):
ifif notnot self..name::
self..name == self..course..name
Default Values
Specify the initial value to use in a form:
classclass Session((Model):):
_name == 'openacademy.session'
......
active == fields..Boolean((default==True))
start_date == fields..Date((default==fields..Date..today))
......
Model Constraints
Prevent bad data:
fromfrom odoo.exceptions importimport WarningWarning
classclass Session((Model):):
_name == 'openacademy.session'
......
@api.one@api.one
@api.constrains@api.constrains(('instructor',, 'attendees'))
defdef _check_instructor((self):):
ifif self..instructor inin self..attendees::
raiseraise WarningWarning(("Instructor of session '%s' "
"cannot attend its own session" %% self..name))
More Stuff
Extend existing models
Many view types
Workflows
Reports
Security
Translations
·
·
·
·
·
·
Backend Modules in V8
Conclusion
Modules have a simple structure
Model definition intuitive and efficient
uses Python standards (decorators, descriptors)
recordsets provide support for "batch" processing
many model hooks (default values, constraints,
computed fields)
·
·
·
·
·

Odoo - Backend modules in v8

  • 1.
    Backend Modules inV8 Raphael Collet (rco@odoo.com)
  • 2.
  • 3.
  • 4.
    Architecture of Odoo Three-tierclient/server/database Web client in Javascript Server and backend modules in Python MVC framework · · · ·
  • 5.
  • 6.
    The Module Manage courses,sessions, and subscriptions Learn Structure of a module Definition of data models Definition of views and menus · · · · ·
  • 7.
    Structure of aModule An Odoo module is a python module (data models), with a manifest file, XML and CSV data files (base data, views, menus), frontend resources (Javascript, CSS). · · · ·
  • 8.
    The Open AcademyModule The manifest file __odoo__.py: {{ 'name':: 'Open Academy',, 'version':: '1.0',, 'category':: 'Tools',, 'summary':: 'Courses, Sessions, Subscriptions',, 'description':: "...",, 'depends' :: [['base'],], 'data' :: [['view/menu.xml'],], 'images':: [],[], 'demo':: [],[], 'application':: True,, }}
  • 9.
    The Course Model Amodel and its fields are defined in a Python class: fromfrom odoo importimport Model,, fields classclass Course((Model):): _name == 'openacademy.course' name == fields..Char((string=='Title',, required==True)) description == fields..Text()()
  • 10.
    The Menu asXML data <?xml version="1.0" encoding="UTF-8"?> <openerp><openerp> <data><data> <menuitem<menuitem name="Open Academy" id="menu_root" sequence="110"/>/> <menuitem<menuitem name="General" id="menu_general" parent="menu_root"/>/> <record<record model="ir.actions.act_window" id="action_courses">> <field<field name="name">>Courses</field></field> <field<field name="res_model">>openacademy.course</field></field> <field<field name="view_mode">>tree,form</field></field> </record></record> <menuitem<menuitem name="Courses" id="menu_courses" parent="menu_general" sequence="1" action="action_courses"/>/> </data></data> </openerp></openerp>
  • 11.
    Let's add aForm View <record<record model="ir.ui.view" id="course_form">> <field<field name="name">>course form view</field></field> <field<field name="model">>openacademy.course</field></field> <field<field name="arch" type="xml">> <form<form string="Course" version="7.0">> <sheet><sheet> <h1><h1> <field<field name="name" placeholder="Course Title"/>/> </h1></h1> <notebook><notebook> <page<page string="Description">> <field<field name="description"/>/> </page></page> </notebook></notebook> </sheet></sheet> </form></form> </field></field> </record></record>
  • 12.
    The Session Model classclassSession((Model):): _name == 'openacademy.session' name == fields..Char((required==True)) start_date == fields..Date()() duration == fields..Integer((help=="Duration in days")) seats == fields..Integer((string=="Number of Seats"))
  • 13.
    Relational Fields Let uslink sessions to courses and instructors: classclass Session((Model):): _name == 'openacademy.session' ...... course == fields..Many2one(('openacademy.course',, required==True)) instructor == fields..Many2one(('res.partner'))
  • 14.
    Relational Fields Let usback-link courses and sessions: classclass Course((Model):): _name == 'openacademy.course' ...... responsible == fields..Many2one(('res.users')) sessions == fields..One2many(('openacademy.session',, 'course'))
  • 15.
    Relational Fields Let uslink sessions to partners for attendee subscription: classclass Session((Model):): _name == 'openacademy.session' ...... attendees == fields..Many2many(('res.partner'))
  • 16.
    Computed Fields The valueof those fields is computed: classclass Session((Model):): _name == 'openacademy.session' ...... taken_seats == fields..Float((compute=='_compute_taken_seats')) @api.one@api.one @api.depends@api.depends(('attendees',, 'seats')) defdef _compute_taken_seats((self):): ifif self..seats:: self..taken_seats == 100.0100.0 ** len((self..attendees)) // self..seats elseelse:: self..taken_seats == 0.00.0
  • 17.
    About self Model instancesare recordsetsrecordsets. A recordset is an hybrid concept: collection of records record forfor session inin self:: printprint session..name printprint session..course..name assertassert self..name ==== self[[00]]..name · ·
  • 18.
    Feedback with "Onchange" Methods Modifyform values when some field is filled in: classclass Session((Model):): _name == 'openacademy.session' ...... @api.onchange@api.onchange(('course')) defdef _onchange_course((self):): ifif notnot self..name:: self..name == self..course..name
  • 19.
    Default Values Specify theinitial value to use in a form: classclass Session((Model):): _name == 'openacademy.session' ...... active == fields..Boolean((default==True)) start_date == fields..Date((default==fields..Date..today)) ......
  • 20.
    Model Constraints Prevent baddata: fromfrom odoo.exceptions importimport WarningWarning classclass Session((Model):): _name == 'openacademy.session' ...... @api.one@api.one @api.constrains@api.constrains(('instructor',, 'attendees')) defdef _check_instructor((self):): ifif self..instructor inin self..attendees:: raiseraise WarningWarning(("Instructor of session '%s' " "cannot attend its own session" %% self..name))
  • 21.
    More Stuff Extend existingmodels Many view types Workflows Reports Security Translations · · · · · ·
  • 22.
  • 23.
    Conclusion Modules have asimple structure Model definition intuitive and efficient uses Python standards (decorators, descriptors) recordsets provide support for "batch" processing many model hooks (default values, constraints, computed fields) · · · · ·