Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

odoo_pyclient-1.0.0.tar.gz (11.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

odoo_pyclient-1.0.0-py3-none-any.whl (7.6 kB view details)

Uploaded Python 3

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

Hashes for odoo_pyclient-1.0.0.tar.gz
Algorithm Hash digest
SHA256 290f4e49369127b0229142a926dbf190f9fd12210c59fd8f423c321a66c56bc0
MD5 41f359647a2cd5a5d6a9ab2ca0b9b297
BLAKE2b-256 1284ad85d81d2532617b218df2f3f0f8c3383742af3bc01abc6eb80d4c5eafd2

See more details on using hashes here.

Provenance

The following attestation bundles were made for odoo_pyclient-1.0.0.tar.gz:

Publisher: publish.yml on mohamed-helmy/OdooPyClient

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for odoo_pyclient-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 34be0d2c3593c36fa831c1437ace549f4f3ccde257b93158eb21baac49c3662c
MD5 f4d806a3592ebb5666d25e8194a30eea
BLAKE2b-256 e4f49271056e524c2c5d40a7af9517d34e6a245bdaadd8160c2b1d5c5f761831

See more details on using hashes here.

Provenance

The following attestation bundles were made for odoo_pyclient-1.0.0-py3-none-any.whl:

Publisher: publish.yml on mohamed-helmy/OdooPyClient

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page