SlideShare una empresa de Scribd logo
1 de 26
Descargar para leer sin conexión
2019
Odoo Experience
New Framework / ORM
Fabien Pinckaers • Founder
Odoo 13: the biggest
ORM refactoring
since OpenERP 8
Odoo 13: the biggest
ORM refactoring
since OpenERP 8
In-Memory ORM
Performance: Time
4.5x faster, on average
Performance: SQL
4x less SQL queries, on average → faster perf on larger DB
Perf Demo
Evolution of The ORM for
Perf Improvements
Single Cache
Instead of one cache per env / context
➔ Stored fields have a single value
➔ Computed, non-stored fields’ value
depends on specific keywords in the
context
➔ ex: translatable, properties
v12 cache structure:
➔ {env: {field: {id: value}}}
v13 cache:
➔ {field: {id: value}}
v13 cache, @depends_context fields:
➔ {field: {id: {context_keys: value}}}
# Odoo 12
self.field # SELECT
r = self.with_context(key=val) # new cache
r.field # SELECT
self.sudo().field # new cache + SELECT
# Odoo 13
self.field # SELECT
r = self.with_context(key=val)
r.field
self.sudo().field
Prefer In-Memory updates
Instead of SQL queries
➔ put in cache, instead of writing in DB
➔ env.all.towrite contains values to UPDATE
➔ nearly never invalidate cache, update it
instead (e.g. changing a many2one, will
update cached values of its one2many)
➔ flush([fields]):
◆ write in DB (minimize updates)
◆ recompute optional fields
◆ called at end of rpc
➔ create() does INSERT directly
# Odoo 12
self.name = 'test' # UPDATE + invalid cache
self.name = 'test2' # UPDATE + invalid cache
self.name # SELECT
# Odoo 13
self.name = 'test' # put in cache
self.name = 'test2' # put in cache
self.name # get from cache
self.flush() # UPDATE
Dependencies In-Memory
class order(Model):
discount = Float()
line_ids = One2many('order_id')
class order_line(Model):
order_id = Many2one('order')
price = Float()
subtotal = Float(compute="get_total")
@api.depends('price','order_id.discount')
def get_total(self):
self.subtotal = self.price * self.order_id.discount
# Odoo 12
for order in self:
order.discount = 10.0 # SELECT id WHERE order_id
# UPDATE order
# Odoo 13
for order in self:
order.discount = 10.0 # no SQL
self.flush() # UPDATE order WHERE id IN ()
Whenever possible
➔ instead of SQL query, get inverse field, ex:
to evaluate @depends(‘order_id’), check
value of line_ids in the cache
➔ usually avoids a SELECT as the
implementation of the compute will read the
same object
➔ if no inverse field, fall back to SQL query
(e.g. many2one without a one2many)
➔ when create(), set one2many to []
Delay computed field
As late as possible
➔ compute fields:
◆ only if you read it
◆ or if you need to flush in the DB
➔ as the old value stays in memory, we can
optimize to not recompute if the value do
not change
# odoo 12
for line in order:
line.product_qty = 1 # mark to recompute
# compute l.subtotal, o.total
line.discount = 10 # mark to recompute
# compute l.subtotal, o.total
line.price = 100 # mark to recompute
# compute l.subtotal, o.total
# odoo 13
for line in order:
line.product_qty = 1 # mark to recompute
line.discount = 10 # mark to recompute
line.price = 100 # mark to recompute
self.flush() # recompute all lines & orders
Delay SQL updates
As late as possible
➔ save all changes in a self.env.all.towrite
➔ optimize updates, to minimize queries:
update several records at once
update several fields at once
# odoo 12
for line in order:
line.state = 'draft' # UPDATE ... WHERE ID = x
# odoo 13
for line in order:
line.state = 'draft'
self.flush() # UPDATE ... WHERE ID IN (...)
Optimize dependency tree
to reduce python & sql computations
v12: recursive dependencies
change order.discount
→ order_line.subtotal depends on it
→ to recompute subtotal
→ order_id.total depends on it (for each line)
→ to recompute order.total
v13: optimized dependency trees
change order.discount
→ to recompute total
→ order_line.subtotal depends on it
→ to recompute order_line.subtotal
class order(Model):
discount = Float()
line_ids = One2many('order_id')
class order_line(Model):
order_id = Many2one('order')
price = Float()
subtotal = Float(compute="get_total")
@api.depends('price','order_id.discount')
def get_total(self):
self.subtotal = self.price * self.order_id.discount
# Impact of:
order.discount = 1
browse() optimization
Avoid multiple format conversion
➔ cache format similar to DB to avoid
conversion:
None instead of False
4 instead of (4,) for many2one
➔ don’t convert to read() format, for browse
records
# Odoo 12
self.field
→ prefetch
→ read
→ _read
SQL query
convert_to_cache
put in cache
→ get from cache (convert_to_record)
→ convert_to_read
# Odoo 13
self.field
→ prefetch
_read
SQL query
put in cache
And a lot of code cleanup,
and Python optimization.
Demonstration
speed + SQL
on the way to deprecate
onchange()
Who can tell what
onchange_partner_id()
does on a sale.order?
(not me)
How is the sale.order
pricelist_id field computed?
And the delivery address?
(much easier to express)
Compute vs onchange
Computed Fields
✓ Work in Python module & JS client
✓ Clean dependency graph
✓ Express a business logic
✓ Separation of business concepts
⛌ Field readonly (but can be inverted)
onchange() method
⛌ Only work in JS client
⛌ No dependency graph: recursion
⛌ interface logic, not business logic
⛌ Business concepts aggregated
✓ Allow to edit the field
The new framework supports fields with:
compute=”...”, readonly=False
compute method might not set a value
Compute vs onchange
Example: Definition
onchange() → compute()
# Odoo 12
pricelist_id = fields.Many2one()
delivery_id = fields.Many2one()
@api.onchange('partner_id')
def onchange_partner_id(self):
for order in self:
order.pricelist_id = order.partner_id.pricelist_id
order.delivery_id = order.partner_id.pricelist_id
# Odoo 13
pricelist_id = fields.Many2one(compute="comp_pl_id",
readonly=False)
delivery_id = fields.Many2one(compute="comp_delivery_id")
@api.depends('partner_id')
def compute_pricelist_id(self):
for order in self:
self.pricelist_id = order.partner_id.pricelist_id
@api.depends('partner_id')
def compute_delivery_id(self):
for order in self:
self.delivery_id = order.partner_id.pricelist_id
➔ reverse the definition: instead of telling
what field is impacted by a change, express
the business logic of each field (how is it
computed)
Example: Definition
onchange() → compute()
# Odoo 12
pricelist_id = fields.Many2one()
delivery_id = fields.Many2one()
@api.onchange('partner_id')
def onchange_partner_id(self):
for order in self:
order.pricelist_id = order.partner_id.pricelist_id
order.delivery_id = order.partner_id.pricelist_id
# Odoo 13
pricelist_id = fields.Many2one(
related="partner_id.pricelist_id",
depends="partner_id",
readonly=False,
store=True)
➔ reverse the definition: instead of telling
what field is impacted by a change, express
the business logic of each field (how is it
computed)
Advantages
onchange() → compute()
➔ compute() fields are tested automatically
➔ inheritances simplified
➔ business logic abstraction
➔ code simplification (no need to call
onchange() manually anymore)
Example
l10n_co adds a customer_type field on
account.invoice that depends on
fiscal_position_id?
→ compare onchange vs compute...
# Odoo 13, create an invoice
self.create({
'partner_id': 1,
'line_ids': ([0,0, {'product_id': 2}])
})
# Odoo 13, create another invoice
self.create({
'partner_id': 1,
'payment_term_id': 2,
'line_ids': ([0,0, {
'product_id': 2, 'price_unit': 100.0
}])
})
Status: compute with
readonly=False are in v13.
onchange() still supported but
will be deprecated in the future.
2019
Questions?
Tweet #odooexperience if you enjoyed the presentation

Más contenido relacionado

La actualidad más candente

Tips on how to improve the performance of your custom modules for high volume...
Tips on how to improve the performance of your custom modules for high volume...Tips on how to improve the performance of your custom modules for high volume...
Tips on how to improve the performance of your custom modules for high volume...
Odoo
 
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Odoo
 
pg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLpg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQL
Command Prompt., Inc
 
MongoDB Journaling and the Storage Enginer
MongoDB Journaling and the Storage EnginerMongoDB Journaling and the Storage Enginer
MongoDB Journaling and the Storage Enginer
MongoDB
 

La actualidad más candente (20)

Common Performance Pitfalls in Odoo apps
Common Performance Pitfalls in Odoo appsCommon Performance Pitfalls in Odoo apps
Common Performance Pitfalls in Odoo apps
 
Tips on how to improve the performance of your custom modules for high volume...
Tips on how to improve the performance of your custom modules for high volume...Tips on how to improve the performance of your custom modules for high volume...
Tips on how to improve the performance of your custom modules for high volume...
 
Odoo Online platform: architecture and challenges
Odoo Online platform: architecture and challengesOdoo Online platform: architecture and challenges
Odoo Online platform: architecture and challenges
 
Asynchronous JS in Odoo
Asynchronous JS in OdooAsynchronous JS in Odoo
Asynchronous JS in Odoo
 
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
 
Empower your App by Inheriting from Odoo Mixins
Empower your App by Inheriting from Odoo MixinsEmpower your App by Inheriting from Odoo Mixins
Empower your App by Inheriting from Odoo Mixins
 
QWeb Report in odoo
QWeb Report in odooQWeb Report in odoo
QWeb Report in odoo
 
MongoDB Backup & Disaster Recovery
MongoDB Backup & Disaster RecoveryMongoDB Backup & Disaster Recovery
MongoDB Backup & Disaster Recovery
 
Tutorial: Develop an App with the Odoo Framework
Tutorial: Develop an App with the Odoo FrameworkTutorial: Develop an App with the Odoo Framework
Tutorial: Develop an App with the Odoo Framework
 
Odoo (Build module, Security, ORM)
Odoo (Build module, Security, ORM)Odoo (Build module, Security, ORM)
Odoo (Build module, Security, ORM)
 
Docx Report Module
Docx Report ModuleDocx Report Module
Docx Report Module
 
odoo 11.0 development (CRUD)
odoo 11.0 development (CRUD)odoo 11.0 development (CRUD)
odoo 11.0 development (CRUD)
 
Discover GraphQL with Python, Graphene and Odoo
Discover GraphQL with Python, Graphene and OdooDiscover GraphQL with Python, Graphene and Odoo
Discover GraphQL with Python, Graphene and Odoo
 
MongoDB
MongoDBMongoDB
MongoDB
 
MongoDB: How it Works
MongoDB: How it WorksMongoDB: How it Works
MongoDB: How it Works
 
MongoDB Schema Design
MongoDB Schema DesignMongoDB Schema Design
MongoDB Schema Design
 
pg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLpg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQL
 
Mongo DB schema design patterns
Mongo DB schema design patternsMongo DB schema design patterns
Mongo DB schema design patterns
 
MongoDB Journaling and the Storage Enginer
MongoDB Journaling and the Storage EnginerMongoDB Journaling and the Storage Enginer
MongoDB Journaling and the Storage Enginer
 
Introduction to MongoDB
Introduction to MongoDBIntroduction to MongoDB
Introduction to MongoDB
 

Similar a New Framework - ORM

Presentation of the new OpenERP API. Raphael Collet, OpenERP
Presentation of the new OpenERP API. Raphael Collet, OpenERPPresentation of the new OpenERP API. Raphael Collet, OpenERP
Presentation of the new OpenERP API. Raphael Collet, OpenERP
Odoo
 
From mysql to MongoDB(MongoDB2011北京交流会)
From mysql to MongoDB(MongoDB2011北京交流会)From mysql to MongoDB(MongoDB2011北京交流会)
From mysql to MongoDB(MongoDB2011北京交流会)
Night Sailer
 
GHC Participant Training
GHC Participant TrainingGHC Participant Training
GHC Participant Training
AidIQ
 
Solutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
Solutions for bi-directional Integration between Oracle RDMBS & Apache KafkaSolutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
Solutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
Guido Schmutz
 
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
confluent
 

Similar a New Framework - ORM (20)

Presentation of the new OpenERP API. Raphael Collet, OpenERP
Presentation of the new OpenERP API. Raphael Collet, OpenERPPresentation of the new OpenERP API. Raphael Collet, OpenERP
Presentation of the new OpenERP API. Raphael Collet, OpenERP
 
Code is not text! How graph technologies can help us to understand our code b...
Code is not text! How graph technologies can help us to understand our code b...Code is not text! How graph technologies can help us to understand our code b...
Code is not text! How graph technologies can help us to understand our code b...
 
MongoDB Aggregation Framework
MongoDB Aggregation FrameworkMongoDB Aggregation Framework
MongoDB Aggregation Framework
 
Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0
 
Drupal II: The SQL
Drupal II: The SQLDrupal II: The SQL
Drupal II: The SQL
 
Distributed Queries in IDS: New features.
Distributed Queries in IDS: New features.Distributed Queries in IDS: New features.
Distributed Queries in IDS: New features.
 
From mysql to MongoDB(MongoDB2011北京交流会)
From mysql to MongoDB(MongoDB2011北京交流会)From mysql to MongoDB(MongoDB2011北京交流会)
From mysql to MongoDB(MongoDB2011北京交流会)
 
mongodb-introduction
mongodb-introductionmongodb-introduction
mongodb-introduction
 
GHC Participant Training
GHC Participant TrainingGHC Participant Training
GHC Participant Training
 
Odoo from 7.0 to 8.0 API
Odoo from 7.0 to 8.0 APIOdoo from 7.0 to 8.0 API
Odoo from 7.0 to 8.0 API
 
Odoo - From v7 to v8: the new api
Odoo - From v7 to v8: the new apiOdoo - From v7 to v8: the new api
Odoo - From v7 to v8: the new api
 
Fatc
FatcFatc
Fatc
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
 
MongoDB Meetup
MongoDB MeetupMongoDB Meetup
MongoDB Meetup
 
Solutions for bi-directional integration between Oracle RDBMS & Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS & Apache KafkaSolutions for bi-directional integration between Oracle RDBMS & Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS & Apache Kafka
 
Drupal - dbtng 25th Anniversary Edition
Drupal - dbtng 25th Anniversary EditionDrupal - dbtng 25th Anniversary Edition
Drupal - dbtng 25th Anniversary Edition
 
Solutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
Solutions for bi-directional Integration between Oracle RDMBS & Apache KafkaSolutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
Solutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
 
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
 
PHP and COM
PHP and COMPHP and COM
PHP and COM
 
MongoDB World 2018: Keynote
MongoDB World 2018: KeynoteMongoDB World 2018: Keynote
MongoDB World 2018: Keynote
 

Más de Odoo

Más de Odoo (20)

Timesheet Workshop: The Timesheet App People Love!
Timesheet Workshop: The Timesheet App People Love!Timesheet Workshop: The Timesheet App People Love!
Timesheet Workshop: The Timesheet App People Love!
 
Odoo 3D Product View with Google Model-Viewer
Odoo 3D Product View with Google Model-ViewerOdoo 3D Product View with Google Model-Viewer
Odoo 3D Product View with Google Model-Viewer
 
Keynote - Vision & Strategy
Keynote - Vision & StrategyKeynote - Vision & Strategy
Keynote - Vision & Strategy
 
Opening Keynote - Unveilling Odoo 14
Opening Keynote - Unveilling Odoo 14Opening Keynote - Unveilling Odoo 14
Opening Keynote - Unveilling Odoo 14
 
Extending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting CapabilityExtending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting Capability
 
Managing Multi-channel Selling with Odoo
Managing Multi-channel Selling with OdooManaging Multi-channel Selling with Odoo
Managing Multi-channel Selling with Odoo
 
Product Configurator: Advanced Use Case
Product Configurator: Advanced Use CaseProduct Configurator: Advanced Use Case
Product Configurator: Advanced Use Case
 
Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?
 
Rock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced OperationsRock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced Operations
 
Transition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organizationTransition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organization
 
Synchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the CrisisSynchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the Crisis
 
Running a University with Odoo
Running a University with OdooRunning a University with Odoo
Running a University with Odoo
 
Down Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in OdooDown Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in Odoo
 
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach foodOdoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
 
Migration from Salesforce to Odoo
Migration from Salesforce to OdooMigration from Salesforce to Odoo
Migration from Salesforce to Odoo
 
Preventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine LearningPreventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine Learning
 
Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification
 
Instant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping LabelInstant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping Label
 
How Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 FoldHow Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 Fold
 
From Shopify to Odoo
From Shopify to OdooFrom Shopify to Odoo
From Shopify to Odoo
 

Último

Jual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan Cytotec
Jual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan CytotecJual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan Cytotec
Jual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan Cytotec
ZurliaSoop
 
obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...
obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...
obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...
yulianti213969
 

Último (20)

Berhampur 70918*19311 CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
Berhampur 70918*19311 CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDINGBerhampur 70918*19311 CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
Berhampur 70918*19311 CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
 
Falcon Invoice Discounting: The best investment platform in india for investors
Falcon Invoice Discounting: The best investment platform in india for investorsFalcon Invoice Discounting: The best investment platform in india for investors
Falcon Invoice Discounting: The best investment platform in india for investors
 
Jual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan Cytotec
Jual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan CytotecJual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan Cytotec
Jual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan Cytotec
 
WheelTug Short Pitch Deck 2024 | Byond Insights
WheelTug Short Pitch Deck 2024 | Byond InsightsWheelTug Short Pitch Deck 2024 | Byond Insights
WheelTug Short Pitch Deck 2024 | Byond Insights
 
Getting Real with AI - Columbus DAW - May 2024 - Nick Woo from AlignAI
Getting Real with AI - Columbus DAW - May 2024 - Nick Woo from AlignAIGetting Real with AI - Columbus DAW - May 2024 - Nick Woo from AlignAI
Getting Real with AI - Columbus DAW - May 2024 - Nick Woo from AlignAI
 
Bangalore Call Girl Just Call♥️ 8084732287 ♥️Top Class Call Girl Service Avai...
Bangalore Call Girl Just Call♥️ 8084732287 ♥️Top Class Call Girl Service Avai...Bangalore Call Girl Just Call♥️ 8084732287 ♥️Top Class Call Girl Service Avai...
Bangalore Call Girl Just Call♥️ 8084732287 ♥️Top Class Call Girl Service Avai...
 
Call 7737669865 Vadodara Call Girls Service at your Door Step Available All Time
Call 7737669865 Vadodara Call Girls Service at your Door Step Available All TimeCall 7737669865 Vadodara Call Girls Service at your Door Step Available All Time
Call 7737669865 Vadodara Call Girls Service at your Door Step Available All Time
 
Paradip CALL GIRL❤7091819311❤CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
Paradip CALL GIRL❤7091819311❤CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDINGParadip CALL GIRL❤7091819311❤CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
Paradip CALL GIRL❤7091819311❤CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
 
Berhampur Call Girl Just Call 8084732287 Top Class Call Girl Service Available
Berhampur Call Girl Just Call 8084732287 Top Class Call Girl Service AvailableBerhampur Call Girl Just Call 8084732287 Top Class Call Girl Service Available
Berhampur Call Girl Just Call 8084732287 Top Class Call Girl Service Available
 
Buy gmail accounts.pdf buy Old Gmail Accounts
Buy gmail accounts.pdf buy Old Gmail AccountsBuy gmail accounts.pdf buy Old Gmail Accounts
Buy gmail accounts.pdf buy Old Gmail Accounts
 
obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...
obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...
obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...
 
Lundin Gold - Q1 2024 Conference Call Presentation (Revised)
Lundin Gold - Q1 2024 Conference Call Presentation (Revised)Lundin Gold - Q1 2024 Conference Call Presentation (Revised)
Lundin Gold - Q1 2024 Conference Call Presentation (Revised)
 
Chennai Call Gril 80022//12248 Only For Sex And High Profile Best Gril Sex Av...
Chennai Call Gril 80022//12248 Only For Sex And High Profile Best Gril Sex Av...Chennai Call Gril 80022//12248 Only For Sex And High Profile Best Gril Sex Av...
Chennai Call Gril 80022//12248 Only For Sex And High Profile Best Gril Sex Av...
 
Nashik Call Girl Just Call 7091819311 Top Class Call Girl Service Available
Nashik Call Girl Just Call 7091819311 Top Class Call Girl Service AvailableNashik Call Girl Just Call 7091819311 Top Class Call Girl Service Available
Nashik Call Girl Just Call 7091819311 Top Class Call Girl Service Available
 
UAE Bur Dubai Call Girls ☏ 0564401582 Call Girl in Bur Dubai
UAE Bur Dubai Call Girls ☏ 0564401582 Call Girl in Bur DubaiUAE Bur Dubai Call Girls ☏ 0564401582 Call Girl in Bur Dubai
UAE Bur Dubai Call Girls ☏ 0564401582 Call Girl in Bur Dubai
 
Durg CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN durg ESCORTS
Durg CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN durg ESCORTSDurg CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN durg ESCORTS
Durg CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN durg ESCORTS
 
JAJPUR CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN JAJPUR ESCORTS
JAJPUR CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN JAJPUR  ESCORTSJAJPUR CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN JAJPUR  ESCORTS
JAJPUR CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN JAJPUR ESCORTS
 
GUWAHATI 💋 Call Girl 9827461493 Call Girls in Escort service book now
GUWAHATI 💋 Call Girl 9827461493 Call Girls in  Escort service book nowGUWAHATI 💋 Call Girl 9827461493 Call Girls in  Escort service book now
GUWAHATI 💋 Call Girl 9827461493 Call Girls in Escort service book now
 
Lucknow Housewife Escorts by Sexy Bhabhi Service 8250092165
Lucknow Housewife Escorts  by Sexy Bhabhi Service 8250092165Lucknow Housewife Escorts  by Sexy Bhabhi Service 8250092165
Lucknow Housewife Escorts by Sexy Bhabhi Service 8250092165
 
Only Cash On Delivery Call Girls In Sikandarpur Gurgaon ❤️8448577510 ⊹Escorts...
Only Cash On Delivery Call Girls In Sikandarpur Gurgaon ❤️8448577510 ⊹Escorts...Only Cash On Delivery Call Girls In Sikandarpur Gurgaon ❤️8448577510 ⊹Escorts...
Only Cash On Delivery Call Girls In Sikandarpur Gurgaon ❤️8448577510 ⊹Escorts...
 

New Framework - ORM

  • 1. 2019 Odoo Experience New Framework / ORM Fabien Pinckaers • Founder
  • 2. Odoo 13: the biggest ORM refactoring since OpenERP 8
  • 3. Odoo 13: the biggest ORM refactoring since OpenERP 8 In-Memory ORM
  • 5. Performance: SQL 4x less SQL queries, on average → faster perf on larger DB
  • 7. Evolution of The ORM for Perf Improvements
  • 8. Single Cache Instead of one cache per env / context ➔ Stored fields have a single value ➔ Computed, non-stored fields’ value depends on specific keywords in the context ➔ ex: translatable, properties v12 cache structure: ➔ {env: {field: {id: value}}} v13 cache: ➔ {field: {id: value}} v13 cache, @depends_context fields: ➔ {field: {id: {context_keys: value}}} # Odoo 12 self.field # SELECT r = self.with_context(key=val) # new cache r.field # SELECT self.sudo().field # new cache + SELECT # Odoo 13 self.field # SELECT r = self.with_context(key=val) r.field self.sudo().field
  • 9. Prefer In-Memory updates Instead of SQL queries ➔ put in cache, instead of writing in DB ➔ env.all.towrite contains values to UPDATE ➔ nearly never invalidate cache, update it instead (e.g. changing a many2one, will update cached values of its one2many) ➔ flush([fields]): ◆ write in DB (minimize updates) ◆ recompute optional fields ◆ called at end of rpc ➔ create() does INSERT directly # Odoo 12 self.name = 'test' # UPDATE + invalid cache self.name = 'test2' # UPDATE + invalid cache self.name # SELECT # Odoo 13 self.name = 'test' # put in cache self.name = 'test2' # put in cache self.name # get from cache self.flush() # UPDATE
  • 10. Dependencies In-Memory class order(Model): discount = Float() line_ids = One2many('order_id') class order_line(Model): order_id = Many2one('order') price = Float() subtotal = Float(compute="get_total") @api.depends('price','order_id.discount') def get_total(self): self.subtotal = self.price * self.order_id.discount # Odoo 12 for order in self: order.discount = 10.0 # SELECT id WHERE order_id # UPDATE order # Odoo 13 for order in self: order.discount = 10.0 # no SQL self.flush() # UPDATE order WHERE id IN () Whenever possible ➔ instead of SQL query, get inverse field, ex: to evaluate @depends(‘order_id’), check value of line_ids in the cache ➔ usually avoids a SELECT as the implementation of the compute will read the same object ➔ if no inverse field, fall back to SQL query (e.g. many2one without a one2many) ➔ when create(), set one2many to []
  • 11. Delay computed field As late as possible ➔ compute fields: ◆ only if you read it ◆ or if you need to flush in the DB ➔ as the old value stays in memory, we can optimize to not recompute if the value do not change # odoo 12 for line in order: line.product_qty = 1 # mark to recompute # compute l.subtotal, o.total line.discount = 10 # mark to recompute # compute l.subtotal, o.total line.price = 100 # mark to recompute # compute l.subtotal, o.total # odoo 13 for line in order: line.product_qty = 1 # mark to recompute line.discount = 10 # mark to recompute line.price = 100 # mark to recompute self.flush() # recompute all lines & orders
  • 12. Delay SQL updates As late as possible ➔ save all changes in a self.env.all.towrite ➔ optimize updates, to minimize queries: update several records at once update several fields at once # odoo 12 for line in order: line.state = 'draft' # UPDATE ... WHERE ID = x # odoo 13 for line in order: line.state = 'draft' self.flush() # UPDATE ... WHERE ID IN (...)
  • 13. Optimize dependency tree to reduce python & sql computations v12: recursive dependencies change order.discount → order_line.subtotal depends on it → to recompute subtotal → order_id.total depends on it (for each line) → to recompute order.total v13: optimized dependency trees change order.discount → to recompute total → order_line.subtotal depends on it → to recompute order_line.subtotal class order(Model): discount = Float() line_ids = One2many('order_id') class order_line(Model): order_id = Many2one('order') price = Float() subtotal = Float(compute="get_total") @api.depends('price','order_id.discount') def get_total(self): self.subtotal = self.price * self.order_id.discount # Impact of: order.discount = 1
  • 14. browse() optimization Avoid multiple format conversion ➔ cache format similar to DB to avoid conversion: None instead of False 4 instead of (4,) for many2one ➔ don’t convert to read() format, for browse records # Odoo 12 self.field → prefetch → read → _read SQL query convert_to_cache put in cache → get from cache (convert_to_record) → convert_to_read # Odoo 13 self.field → prefetch _read SQL query put in cache
  • 15. And a lot of code cleanup, and Python optimization.
  • 17. on the way to deprecate onchange()
  • 18. Who can tell what onchange_partner_id() does on a sale.order? (not me)
  • 19. How is the sale.order pricelist_id field computed? And the delivery address? (much easier to express)
  • 20. Compute vs onchange Computed Fields ✓ Work in Python module & JS client ✓ Clean dependency graph ✓ Express a business logic ✓ Separation of business concepts ⛌ Field readonly (but can be inverted) onchange() method ⛌ Only work in JS client ⛌ No dependency graph: recursion ⛌ interface logic, not business logic ⛌ Business concepts aggregated ✓ Allow to edit the field The new framework supports fields with: compute=”...”, readonly=False compute method might not set a value
  • 22. Example: Definition onchange() → compute() # Odoo 12 pricelist_id = fields.Many2one() delivery_id = fields.Many2one() @api.onchange('partner_id') def onchange_partner_id(self): for order in self: order.pricelist_id = order.partner_id.pricelist_id order.delivery_id = order.partner_id.pricelist_id # Odoo 13 pricelist_id = fields.Many2one(compute="comp_pl_id", readonly=False) delivery_id = fields.Many2one(compute="comp_delivery_id") @api.depends('partner_id') def compute_pricelist_id(self): for order in self: self.pricelist_id = order.partner_id.pricelist_id @api.depends('partner_id') def compute_delivery_id(self): for order in self: self.delivery_id = order.partner_id.pricelist_id ➔ reverse the definition: instead of telling what field is impacted by a change, express the business logic of each field (how is it computed)
  • 23. Example: Definition onchange() → compute() # Odoo 12 pricelist_id = fields.Many2one() delivery_id = fields.Many2one() @api.onchange('partner_id') def onchange_partner_id(self): for order in self: order.pricelist_id = order.partner_id.pricelist_id order.delivery_id = order.partner_id.pricelist_id # Odoo 13 pricelist_id = fields.Many2one( related="partner_id.pricelist_id", depends="partner_id", readonly=False, store=True) ➔ reverse the definition: instead of telling what field is impacted by a change, express the business logic of each field (how is it computed)
  • 24. Advantages onchange() → compute() ➔ compute() fields are tested automatically ➔ inheritances simplified ➔ business logic abstraction ➔ code simplification (no need to call onchange() manually anymore) Example l10n_co adds a customer_type field on account.invoice that depends on fiscal_position_id? → compare onchange vs compute... # Odoo 13, create an invoice self.create({ 'partner_id': 1, 'line_ids': ([0,0, {'product_id': 2}]) }) # Odoo 13, create another invoice self.create({ 'partner_id': 1, 'payment_term_id': 2, 'line_ids': ([0,0, { 'product_id': 2, 'price_unit': 100.0 }]) })
  • 25. Status: compute with readonly=False are in v13. onchange() still supported but will be deprecated in the future.
  • 26. 2019 Questions? Tweet #odooexperience if you enjoyed the presentation