Python client for Odoo using the requests library and JSON-RPC
Project description
OdooPyClient
Python client library for Odoo using the requests library and JSON-RPC.
Quick Start
from odoo_client import OdooPyClient
# Connect to Odoo
odoo = OdooPyClient(
host='http://localhost',
port=8069,
database='odoo',
username='admin',
password='admin'
)
# Authenticate
odoo.authenticate()
# Search and read records
products = odoo.search_read(
model='product.product',
domain=[['sale_ok', '=', True]],
fields=['name', 'lst_price'],
limit=10
)
# Create a record
partner_id = odoo.create(
model='res.partner',
values={'name': 'John Doe', 'email': 'john@example.com'}
)
# Update a record
odoo.update(
model='res.partner',
ids=partner_id,
values={'phone': '+1234567890'}
)
# Delete a record
odoo.delete(model='res.partner', ids=partner_id)
Installation
Install from PyPI:
pip install odoo-pyclient
Or install from source:
git clone https://github.com/mohamed-helmy/OdooPyClient.git
cd OdooPyClient
pip install -r requirements.txt
Usage
Please refer to the Odoo API documentation if you need help structuring your database queries.
Creating Odoo connection instance
Before executing any kind of query operations, a connection instance must be established either with a username/password or with a previously retrieved session id.
from odoo_client import OdooPyClient
odoo = OdooPyClient(
host='http://localhost',
port=8069, # Defaults to 80 if not specified
database='your_database_name',
username='your_username', # Optional if using a stored session_id
password='your_password', # Optional if using a stored session_id
session_id='your_session_id', # Optional if using username/password
context={'lang': 'en_US'}, # Optional - context like language
)
authenticate
Authenticate with the Odoo server. Returns user data including a session id which can be stored for future connections and session persistence.
try:
result = odoo.authenticate()
print(f"Session ID: {odoo.session_id}")
print(f"User ID: {result.get('uid')}")
except Exception as e:
print(f"Authentication failed: {e}")
read
Receives an Odoo database model string and parameters containing the IDs you want to read and the fields you want to retrieve from each result.
Returns a list of results matching the array of IDs provided in the parameters.
# Read partner from server
result = odoo.read(
model='res.partner',
ids=[1, 2, 3, 4, 5],
fields=['name']
)
search_read
Just like the read method, this one receives a model string and parameters. With this method the parameters may include a domain list for filtering purposes (with filter statements similar to SQL's WHERE), limit and offset values for pagination and an order property which can be set to specific fields.
Returns a list of results matching the parameters provided.
result = odoo.search_read(
model='product.product',
domain=[['list_price', '>', '50'], ['list_price', '<', '65']],
fields=['name', 'list_price', 'items'],
order='list_price DESC',
limit=5,
offset=0
)
create
Receives a model string and a values dictionary with properties corresponding to the fields you want to write in the row.
Example: Create a sale order with order lines
# Get a customer
partners = odoo.search_read(
model='res.partner',
domain=[['customer_rank', '>', 0]],
fields=['id', 'name'],
limit=1
)
partner_id = partners[0]['id']
# Get products
products = odoo.search_read(
model='product.product',
domain=[['sale_ok', '=', True]],
fields=['id', 'name', 'lst_price'],
limit=2
)
# Create sale order with order lines
sale_order_id = odoo.create(
model='sale.order',
values={
'partner_id': partner_id,
'order_line': [
(0, 0, {
'product_id': products[0]['id'],
'product_uom_qty': 2,
'price_unit': products[0]['lst_price'],
}),
(0, 0, {
'product_id': products[1]['id'],
'product_uom_qty': 3,
'price_unit': products[1]['lst_price'],
}),
],
}
)
print(f"Created sale order with ID: {sale_order_id}")
update
Receives a model string, a list of IDs (or single ID) related to the rows you want to update in the database, and a values dictionary with properties corresponding to the fields that are going to be updated.
If you need to update several rows in the database you can take advantage of Python's concurrent features (see examples/async_usage.py) to generate and populate updates in parallel.
Example: Update a sale order
result = odoo.update(
model='sale.order',
ids=sale_order_id, # or [1, 2, 3] for multiple IDs
values={
'client_order_ref': 'PO-2025-001',
'note': 'Updated order with client reference',
}
)
print("Sale order updated successfully")
delete
Receives an Odoo database model string and an IDs list (or single ID) corresponding to the rows you want to delete in the database.
Example: Delete a sale order (after canceling)
# First, cancel the order (required before deletion)
odoo.rpc_call(
endpoint='/web/dataset/call_kw',
params={
'model': 'sale.order',
'method': 'action_cancel',
'args': [[sale_order_id]],
'kwargs': {'context': odoo.context}
}
)
# Now delete it
result = odoo.delete(
model='sale.order',
ids=sale_order_id
)
print(f"Order {sale_order_id} deleted successfully")
rpc_call (Generic RPC Call)
If you wish to execute a custom RPC call not represented in this library's methods, you can also run a custom call by passing an endpoint string and a params dictionary. This requires understanding how the Odoo Web API works more thoroughly so you can properly structure the function parameters.
Example 1: Confirm a sale order
result = odoo.rpc_call(
endpoint='/web/dataset/call_kw',
params={
'model': 'sale.order',
'method': 'action_confirm',
'args': [[sale_order_id]],
'kwargs': {'context': odoo.context}
}
)
print("Sale order confirmed")
Example 2: Search for confirmed orders
order_ids = odoo.rpc_call(
endpoint='/web/dataset/call_kw',
params={
'model': 'sale.order',
'method': 'search',
'args': [[['state', '=', 'sale']]],
'kwargs': {
'limit': 5,
'order': 'date_order desc',
'context': odoo.context
}
}
)
print(f"Found {len(order_ids)} confirmed sale orders")
Example 3: Count orders by state
count = odoo.rpc_call(
endpoint='/web/dataset/call_kw',
params={
'model': 'sale.order',
'method': 'search_count',
'args': [[['state', '=', 'draft']]],
'kwargs': {'context': odoo.context}
}
)
print(f"Draft orders: {count}")
Complete Workflow Example
Here's a complete example showing the full lifecycle of a sale order:
from odoo_client import OdooPyClient
# 1. Connect and authenticate
odoo = OdooPyClient(
host='http://localhost',
port=8069,
database='odoo',
username='admin',
password='admin'
)
result = odoo.authenticate()
print(f"Authenticated as user {result['uid']}")
# 2. Create a sale order
partners = odoo.search_read(
model='res.partner',
domain=[['customer_rank', '>', 0]],
fields=['id', 'name'],
limit=1
)
partner_id = partners[0]['id']
products = odoo.search_read(
model='product.product',
domain=[['sale_ok', '=', True]],
fields=['id', 'name', 'lst_price'],
limit=2
)
sale_order_id = odoo.create(
model='sale.order',
values={
'partner_id': partner_id,
'order_line': [
(0, 0, {
'product_id': products[0]['id'],
'product_uom_qty': 2,
'price_unit': products[0]['lst_price'],
})
]
}
)
print(f"Created sale order: {sale_order_id}")
# 3. Read the order
order_data = odoo.read(
model='sale.order',
ids=[sale_order_id],
fields=['name', 'partner_id', 'state', 'amount_total']
)
print(f"Order {order_data[0]['name']}: ${order_data[0]['amount_total']}")
# 4. Update the order
odoo.update(
model='sale.order',
ids=sale_order_id,
values={
'client_order_ref': 'PO-2025-001',
'note': 'Updated via API'
}
)
print("Order updated")
# 5. Confirm the order
odoo.rpc_call(
endpoint='/web/dataset/call_kw',
params={
'model': 'sale.order',
'method': 'action_confirm',
'args': [[sale_order_id]],
'kwargs': {'context': odoo.context}
}
)
print("Order confirmed")
# 6. Search for confirmed orders
order_ids = odoo.rpc_call(
endpoint='/web/dataset/call_kw',
params={
'model': 'sale.order',
'method': 'search',
'args': [[['state', '=', 'sale']]],
'kwargs': {'limit': 5, 'context': odoo.context}
}
)
print(f"Found {len(order_ids)} confirmed orders")
# 7. Cancel and delete (optional)
odoo.rpc_call(
endpoint='/web/dataset/call_kw',
params={
'model': 'sale.order',
'method': 'action_cancel',
'args': [[sale_order_id]],
'kwargs': {'context': odoo.context}
}
)
odoo.delete(model='sale.order', ids=sale_order_id)
print("Order deleted")
Features
- ✅ Authentication with username/password or session ID
- ✅ Session management with cookies
- ✅ CRUD operations (Create, Read, Update, Delete)
- ✅ Search and search_read operations
- ✅ Generic RPC call support
- ✅ Context support (language, timezone, etc.)
Examples
See the examples/ directory for more detailed usage examples:
example.py- Complete sale order workflow (create, read, update, delete)
References
License
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Author
Mohamed Helmy
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file odoo_pyclient-1.0.0.tar.gz.
File metadata
- Download URL: odoo_pyclient-1.0.0.tar.gz
- Upload date:
- Size: 11.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
290f4e49369127b0229142a926dbf190f9fd12210c59fd8f423c321a66c56bc0
|
|
| MD5 |
41f359647a2cd5a5d6a9ab2ca0b9b297
|
|
| BLAKE2b-256 |
1284ad85d81d2532617b218df2f3f0f8c3383742af3bc01abc6eb80d4c5eafd2
|
Provenance
The following attestation bundles were made for odoo_pyclient-1.0.0.tar.gz:
Publisher:
publish.yml on mohamed-helmy/OdooPyClient
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
odoo_pyclient-1.0.0.tar.gz -
Subject digest:
290f4e49369127b0229142a926dbf190f9fd12210c59fd8f423c321a66c56bc0 - Sigstore transparency entry: 586273883
- Sigstore integration time:
-
Permalink:
mohamed-helmy/OdooPyClient@9c3fc2e6020ca298a04dd2c5c09c769da6a3e7f7 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/mohamed-helmy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9c3fc2e6020ca298a04dd2c5c09c769da6a3e7f7 -
Trigger Event:
release
-
Statement type:
File details
Details for the file odoo_pyclient-1.0.0-py3-none-any.whl.
File metadata
- Download URL: odoo_pyclient-1.0.0-py3-none-any.whl
- Upload date:
- Size: 7.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34be0d2c3593c36fa831c1437ace549f4f3ccde257b93158eb21baac49c3662c
|
|
| MD5 |
f4d806a3592ebb5666d25e8194a30eea
|
|
| BLAKE2b-256 |
e4f49271056e524c2c5d40a7af9517d34e6a245bdaadd8160c2b1d5c5f761831
|
Provenance
The following attestation bundles were made for odoo_pyclient-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on mohamed-helmy/OdooPyClient
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
odoo_pyclient-1.0.0-py3-none-any.whl -
Subject digest:
34be0d2c3593c36fa831c1437ace549f4f3ccde257b93158eb21baac49c3662c - Sigstore transparency entry: 586273892
- Sigstore integration time:
-
Permalink:
mohamed-helmy/OdooPyClient@9c3fc2e6020ca298a04dd2c5c09c769da6a3e7f7 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/mohamed-helmy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9c3fc2e6020ca298a04dd2c5c09c769da6a3e7f7 -
Trigger Event:
release
-
Statement type: