Skip to main content

OdooRPC API

Project description

odoorpc-api

A modern FastAPI-based wrapper for Odoo RPC integration, designed to decouple integration logic from the core Odoo server and provide maximum flexibility for third-party ecosystems.

Why odoorpc-api?

This package is intentionally built to keep your integration layer separate from the Odoo server. By decoupling these environments, you gain the freedom to integrate Odoo with various third-party platforms without affecting the core Odoo performance or stability.

Project Roadmap 🚀

This project is currently in an early alpha stage and under active (but gradual) development. While the core foundation is functional, many features are still experimental. Our current roadmap includes several "work-in-progress" ideas that will be added over time:

  • Advanced Authentication: Enhanced OAuth2 and JWT support.
  • Session Management: Secure and persistent session handling.
  • Redis Caching: High-performance data caching to reduce Odoo RPC overhead.
  • Third-Party Logging: Integration with Sentry, BetterStack, or ELK.
  • CLI Scaffolding: Generate routes, schemas, and API structures automatically with a single command.
  • AI Integration: Seamless connection with LLMs (OpenAI, LangChain) for smart data querying.
  • And more... to make Odoo integration smoother than ever.

Contributing

We believe in the power of the community! If you are familiar with Odoo's internal workings or FastAPI best practices, we would love to have your contribution.

Feel free to open issues, submit PRs, or suggest new features to help this package reach its full potential.

License

Distributed under the MIT License.


Example Usage

Project Setup

# Create project
mkdir myproject
cd myproject

# Setup virtual environment
python3.10 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate

# Install the package
pip install odoorpc-api

# Create configuration and entry point
touch .env main.py
mkdir -p routes/purchase
touch routes/purchase/__init__.py routes/purchase/api.py routes/purchase/schema.py

Configuration Management

.env.default (Default values)

# --- Application Settings ---
TITLE=OdooRPC API
VERSION=1.0
DEBUG=True
LOGFILE=True

# --- Server Configuration ---
HOST=127.0.0.1
PORT=9000

# --- Documentation & Swagger ---
API_URL=/docs
SAVE_SESSION_SWAGGER=False

# --- Odoo Backend Connection ---
ODOO_URL=http://127.0.0.1:8069
ODOO_DB=mydb

.env (Local overrides)

PORT=9000
HOST=127.0.0.1

ODOO_URL=http://127.0.0.1:8069
ODOO_DB=mydb

Entry Point

main.py

import uvicorn

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from odoorpc_api.settings import env
from odoorpc_api.exceptions import handling_exception
from odoorpc_api.routes import handling_router
from odoorpc_api.logging_config import LOGGING_CONFIG
from odoorpc_api.middleware import LoggerMiddleware


app = FastAPI(
    title=env.TITLE,
    version=env.VERSION,
    docs_url=env.API_URL, 
    swagger_ui_parameters={
        "persistAuthorization": env.SAVE_SESSION_SWAGGER,
    },
)

handling_exception(app)
handling_router(app)


app.add_middleware(LoggerMiddleware)


app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


if __name__ == '__main__':
    uvicorn.run(
        'main:app',
        host=env.HOST,
        port=env.PORT,
        reload=env.DEBUG,
        server_header=False,
        log_config=LOGGING_CONFIG
    )

Route Implementation

routes/purchase/api.py

from typing import Annotated
from fastapi import APIRouter, Depends, status

from odoorpc_api.jsonrpc import OdooEnv
from odoorpc_api.params import PageParams
from odoorpc_api.responses import PaginationResponse, ListResponse, SingleResponse, BaseResponse
from odoorpc_api.types import ResponseMessage

from .schema import PurchaseList, PurchaseUpdate, model, path


router = APIRouter(tags=["Purchase"])


@router.get(path, status_code=status.HTTP_200_OK, response_model=PaginationResponse[PurchaseList])
def get(q: Annotated[PageParams, Depends()], odoo = OdooEnv):
    data = odoo.search_read(
        model, 
        q.domain, 
        fields=PurchaseList.fields(), 
        limit=q.limit, 
        offset=q.offset,
    )
    total = odoo.search_count(model, q.domain)

    # PaginationResponse
    return {
        'message': ResponseMessage.GET,
        'offset': q.offset,
        'limit': q.limit,
        'total': total,
        'data': data,
    }

    # ListResponse
    # return {
    #     'message': ResponseMessage.GET,
    #     'data': data
    # }

    # SingleResponse
    # return {
    #     'message': ResponseMessage.GET,
    #     'data': data[0] if data else []
    # }

    # BaseResponse
    # return {
    #     'message': ResponseMessage.GET,
    # }


@router.post(path, status_code=status.HTTP_201_CREATED, response_model=ListResponse)
def post(payload: list[PurchaseUpdate] | PurchaseUpdate, odoo = OdooEnv):
    data = odoo.create(model, payload)
    return {
        'message': ResponseMessage.POST,
        'data': data, 
    }


@router.put(path+'/{id}', status_code=status.HTTP_200_OK, response_model=BaseResponse)
def put(id: int, payload: PurchaseUpdate, odoo = OdooEnv):
    odoo.write(model, id, payload)
    return {
        'message': ResponseMessage.PUT,
    }


@router.delete(path+'/id', status_code=status.HTTP_204_NO_CONTENT)
def delete(id: int, odoo = OdooEnv):
    odoo.button_cancel(model, id)
    odoo.unlink(model, id)

Data Schemas

routes/purchase/schema.py

from odoorpc_api.schemas import OdooBaseModel


path = '/purchase'
model = 'purchase.order'


class PurchaseList(OdooBaseModel):
    name: str
    partner_id: int


class PurchaseUpdate(OdooBaseModel):
    partner_id: int

Query Parameters Handling

The framework provides a default PageParams which includes

  • offset
  • limit
  • create_date_from (odoo field create_date)
  • create_date_to (odoo field create_date)
@router.get(path, status_code=status.HTTP_200_OK, response_model=PaginationResponse[PurchaseList])
def get(q: Annotated[PageParams, Depends()], odoo = OdooEnv):

Scenario A: Removing Parameters If you don't need pagination or filtering, simply omit the parameter from the function:

@router.get(path, status_code=status.HTTP_200_OK, response_model=PaginationResponse[PurchaseList])
def get(odoo = OdooEnv):

Scenario B: Custom Parameters Create a custom Pydantic model for specific filtering requirements:

routes/purchase/schema.py or new file routes/purchase/params.py

from datetime import date
from pydantic import BaseModel

class CustomPurchaseParam(BaseModel):
    number: str
    date: date

routes/purchase/api.py

# from .schema import CustomPurchaseParam # from schema.py
from .params import CustomPurchaseParam

@router.get(path, status_code=status.HTTP_200_OK, response_model=PaginationResponse[PurchaseList])
def get(q: Annotated[CustomPurchaseParam, Depends()], odoo = OdooEnv):

Execution

python main.py

# Open: http://127.0.0.1/9000/docs

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

odoorpc_api-0.1.1.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

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

odoorpc_api-0.1.1-py3-none-any.whl (13.8 kB view details)

Uploaded Python 3

File details

Details for the file odoorpc_api-0.1.1.tar.gz.

File metadata

  • Download URL: odoorpc_api-0.1.1.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for odoorpc_api-0.1.1.tar.gz
Algorithm Hash digest
SHA256 16bafbeb61c5551f230445cb77f6d74957983606e00839a3770e911383bb118b
MD5 a35687491ac81bc93b2c0b0a6bf5a6e2
BLAKE2b-256 a9788f488036b50bef06eb20964e00c9cfd02b84b4630483aa4cf7f84a75ac02

See more details on using hashes here.

Provenance

The following attestation bundles were made for odoorpc_api-0.1.1.tar.gz:

Publisher: pypi-publish.yaml on alwy95/odoorpc-api

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

File details

Details for the file odoorpc_api-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: odoorpc_api-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 13.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for odoorpc_api-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 421a5b2b0c75c2bb2466e5b80ce5b24ae66b7a8bc563b1ccba73400691c6a4b0
MD5 f860d0bb3cf101a2116820a9aa8988ec
BLAKE2b-256 e3c481b799bb99d7133bda73cf3bfd355145b49c1cc1afc3c8b41aa3f6028922

See more details on using hashes here.

Provenance

The following attestation bundles were made for odoorpc_api-0.1.1-py3-none-any.whl:

Publisher: pypi-publish.yaml on alwy95/odoorpc-api

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