JSON-RPC
JSON (Javascript Object Notation) is a format for interchange data that is primarily used in applications and APIs. The primary benefit of using JSON is that it is simple to write and parse through the contents. It is simple to read and interpret. To make a remote call to a Python method, we can use RPC (Remote Procedure Call).
Odoo's json-rpc API method allows users to connect to the Odoo server remotely. It is an RPC that has JSON encoding. It's comparable to XML-RPC but much lighter and doesn't need a response to send data to the server than XML-RPC.
Connection to Odoo
Let's look at how the json-rpc method can be used to connect to Odoo.
import json
import json
import random
import urllib.request
host = 'localhost'
port = 8016
database = 'DemoDB'
user = 'admin'
password = 'admin'
def json_rpc(url, method, params):
data = {
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": random.randint(0, 1000000000),
}
req = urllib.request.Request(url=url, data=json.dumps(data).encode(), headers={
"Content-Type":"application/json",
})
reply = json.loads(urllib.request.urlopen(req).read().decode('UTF-8'))
if reply.get("error"):
raise Exception(reply["error"])
return reply["result"]
def call(url, service, method, *args):
return json_rpc(url, "call", {"service": service, "method": method, "args": args})
url = "http://%s:%s/jsonrpc" % (host, port)
uid = call(url, "common", "login", database, user, password)
print(uid)
(Py3.6_venv) cybrosys@cybrosys-shamsad:~/json-rpc$ python3 json-test.py
2
This will give output as the ID of the user.
url: Specifying the URL of JSON-RPC with host and port number
service: Set the service as common
method: Set the method as login
args: Pass the argument as given below:
database: name of database
user: login user id
password: password of user
This will give output as the ID of the user.
Search/ Read Records
We can use JSON RPC to fetch data and to search/ read out data from the database.
import json
import random
import urllib.request
host = 'localhost'
port = 8016
database = 'DemoDB'
user = 'admin'
password = 'admin'
def json_rpc(url, method, params):
data = {
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": random.randint(0, 1000000000),
}
req = urllib.request.Request(url=url, data=json.dumps(data).encode(), headers={
"Content-Type":"application/json",
})
reply = json.loads(urllib.request.urlopen(req).read().decode('UTF-8'))
if reply.get("error"):
raise Exception(reply["error"])
return reply["result"]
def call(url, service, method, *args):
return json_rpc(url, "call", {"service": service, "method": method, "args": args})
url = "http://%s:%s/jsonrpc" % (host, port)
uid = call(url, "common", "login", database, user, password)
task_ids = call(url, "object", "execute", database, uid, password, "project.task", "read", [1])
print("Tasks: ", task_ids)
url: Specifying the url of json-rpc with host and port number
service: Set the service as object
method: Set the method as execute
args: Pass the argument as given below:
database: name of database
uid: id of user
password: password of user
model_name: model name
method: method as read to call the read method
ids: list of ids in which data should read
And the output will be:
python3 json-test.py
Tasks: [{'id': 1, 'rating_ids': [], 'rating_last_value': 0.0, 'rating_last_feedback': False, 'rating_last_image': False, 'rating_count': 0, 'rating_avg': 0.0, 'rating_avg_text': 'none', 'rating_percentage_satisfaction': -1.0, 'rating_last_text': False, 'activity_ids': [], 'activity_state': False, 'activity_user_id': False, 'activity_type_id': False, 'activity_type_icon': False, 'activity_date_deadline': False, 'my_activity_date_deadline': False, 'activity_summary': False, 'activity_exception_decoration': False, 'activity_exception_icon': False, 'message_is_follower': True, 'message_follower_ids': [29, 30, 31], 'message_partner_ids': [3, 7], 'message_ids': [45], 'has_message': True, 'message_needaction': False, 'message_needaction_counter': 0, 'message_has_error': False, 'message_has_error_counter': 0, 'message_attachment_count': 0, 'message_main_attachment_id': False, 'website_message_ids': [], 'message_has_sms_error': False, 'email_cc': False, 'access_url': '/my/tasks/1', 'access_token': '4c36bc36-f60a-4da8-9aa3-c81e05a7079a', 'access_warning': '', 'active': True, 'name': 'Office planning', 'description': False, 'priority': '0', 'sequence': 20, 'stage_id': [3, 'Done'], 'tag_ids': [], 'kanban_state': 'normal', 'kanban_state_label': 'In Progress', 'create_date': '2022-06-05 07:29:59', 'write_date': '2022-11-05 07:29:55', 'date_end': '2022-11-05 07:29:59', 'date_assign': False, 'date_deadline': False, 'date_last_stage_update': '2022-11-05 07:29:59', 'project_id': [1, 'Office Design'], 'task_properties': [], 'display_project_id': [1, 'Office Design'], 'planned_hours': 20.0, 'subtask_planned_hours': 0.0, 'user_ids': [], 'portal_user_names': '', 'personal_stage_type_ids': [], 'personal_stage_id': False, 'personal_stage_type_id': False,
'partner_id': [8, 'YourCompany, Joel Willis'], 'partner_is_company': False, 'commercial_partner_id': [8, 'YourCompany, Joel Willis'], 'partner_email': 'joel.willis63@example.com', 'partner_phone': '(683)-556-5104', 'partner_city': 'Bayonne', 'manager_id': [6, 'Marc Demo'], 'company_id': [1, 'YourCompany'], 'color': 7, 'project_color': 3, 'rating_active': False, 'attachment_ids': [], 'displayed_image_id': False, 'legend_blocked': 'Blocked', 'legend_done': 'Ready', 'legend_normal': 'In Progress', 'is_closed': True, 'parent_id': False, 'ancestor_id': False, 'child_ids': [], 'child_text': False, 'allow_subtasks': False, 'subtask_count': 0, 'email_from': 'joel.willis63@example.com', 'project_privacy_visibility': 'portal', 'working_hours_open': 0.0,
'working_hours_close': 880.0, 'working_days_open': 0.0, 'working_days_close': 110.0, 'is_private': False, 'allow_milestones': True, 'milestone_id': [1, 'First Phase'], 'has_late_and_unreached_milestone': False, 'allow_task_dependencies': False, 'depend_on_ids': [], 'dependent_ids': [], 'dependent_tasks_count': 0, 'is_blocked': False, 'display_parent_task_button': False, 'allow_recurring_tasks': False, 'recurring_task': False, 'recurring_count': 0, 'recurrence_id': False, 'recurrence_update': 'this', 'recurrence_message': False, 'repeat_interval': 0, 'repeat_unit': False, 'repeat_type': False, 'repeat_until': False, 'repeat_number': 0, 'repeat_on_month': False, 'repeat_on_year': False, 'mon': False, 'tue': False, 'wed': False, 'thu': False, 'fri': False, 'sat': False, 'sun': False, 'repeat_day': False, 'repeat_week': False, 'repeat_weekday': False, 'repeat_month': False, 'repeat_show_dow': False, 'repeat_show_day': False, 'repeat_show_week': False, 'repeat_show_month': False, 'analytic_account_id': [19,
'Office Design'], 'is_analytic_account_id_changed': False, 'project_analytic_account_id': [19, 'Office Design'], '__last_update': '2022-11-05 07:29:55', 'display_name': 'Office planning', 'create_uid': [1, 'OdooBot'], 'write_uid': [1, 'OdooBot']}]
If we want to use search read method, we have to replace the task_ids as given below.
task_ids = call(url, "object", "execute", database, uid, password, "project.task", "read", [1])
Create Records
We can create records in the database using JSON-RPC.
Let us see how to create a record:
URL: Specifying the url of json-rpc with host and port number
service: Set the service as object
method: Set the method as execute
args: Arguments to create records
project_args = {
'name': 'JSON_RPC Project 3'
}
project_id = call(url, "object", "execute", database, uid, password, "project.project", "create", project_args)
#Create task only if project is created
if project_id:
task_args = {
'name': 'JSON_RPC Task 1',
'project_id': project_id
}
task_id = call(url, "object", "execute", database, uid, password, "project.task", "create", task_args)
The screenshot below shows the project and task created.
Update Records
project_args = {
'name': 'JSON_RPC Project 3'
}
project_args_update = {
'name': 'JSON_RPC Project updated'
}
project_id = call(url, "object", "execute", database, uid, password, "project.project", "create", project_args)
#Create task only if project is created
if project_id:
project_update = call(url, "object", "execute", database, uid, password, "project.project", "write",project_id ,project_args_update)
It is used to update the records.
Delete Record
project_args = {
'name': 'JSON_RPC Project 3'
}
project_id = call(url, "object", "execute", database, uid, password, "project.project", "create", project_args)
#Create task only if project is created
if project_id:
project_update = call(url, "object", "execute", database, uid, password, "project.project", "unlink", [project_id] )
By using the unlink method we can delete the record created using json-rpc.
Calling Method
import json
import json
import random
import urllib.request
host = 'localhost'
port = 8016
database = 'DemoDB'
user = 'admin'
password = 'admin'
def json_rpc(url, method, params):
data = {
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": random.randint(0, 1000000000),
}
req = urllib.request.Request(url=url, data=json.dumps(data).encode(), headers={
"Content-Type":"application/json",
})
reply = json.loads(urllib.request.urlopen(req).read().decode('UTF-8'))
if reply.get("error"):
raise Exception(reply["error"])
return reply["result"]
def call(url, service, method, *args):
return json_rpc(url, "call", {"service": service, "method": method, "args": args})
url = "http://%s:%s/jsonrpc" % (host, port)
uid = call(url, "common", "login", database, user, password)
print(uid)
Here we mention the URL with host and port. Then we mention the database name, user login, and password. Then we use service and common and method as login to connect to the Odoo database.