From 22a843d1138385ab52570e5fa084f834d5b82883 Mon Sep 17 00:00:00 2001 From: jeffery Date: Tue, 8 Jun 2021 16:44:30 +0800 Subject: [PATCH 1/2] restful in http_request instead of json_request --- README.md | 44 +++++++++++------------- controllers/controllers.py | 69 ++++++++++++++++++++++---------------- 2 files changed, 59 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 25765bc..9d2a634 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ print(res.text) ### Model records: -`GET /api/{model}/` +`GET /rest/{model}/` #### Parameters * **query (optional):** @@ -113,7 +113,7 @@ print(res.text) For nested records, for example if we want to select `id`, `name` and `company_id` fields from `res.users` model, but under `company_id` we want to select `name` field only. here is how we would do it. - `GET /api/res.users/?query={id, name, company_id{name}}` + `GET /rest/res.users/?query={id, name, company_id{name}}` ```js { @@ -143,7 +143,7 @@ print(res.text) For nested iterable records, for example if we want to select `id`, `name` and `related_products` fields from `product.template` model, but under `related_products` we want to select `name` field only. here is how we would do it. - `GET /api/product.template/?query={id, name, related_products{name}}` + `GET /rest/product.template/?query={id, name, related_products{name}}` ```js { @@ -175,7 +175,7 @@ print(res.text) ``` If you want to fetch all fields except few you can use exclude(-) operator. For example in the case above if we want to fetch all fields except `name` field, here is how we could do it - `GET /api/product.template/?query={-name}` + `GET /rest/product.template/?query={-name}` ```js { @@ -200,7 +200,7 @@ print(res.text) There is also a wildcard(\*) operator which can be used to fetch all fields, Below is an example which shows how you can fetch all product's fields but under `related_products` field get all fields except `id`. - `GET /api/product.template/?query={*, related_products{-id}}` + `GET /rest/product.template/?query={*, related_products{-id}}` ```js { @@ -231,7 +231,7 @@ print(res.text) This is used to filter out data returned. For example if we want to get all products with id ranging from 60 to 70, here's how we would do it. - `GET /api/product.template/?query={id, name}&filter=[["id", ">", 60], ["id", "<", 70]]` + `GET /rest/product.template/?query={id, name}&filter=[["id", ">", 60], ["id", "<", 70]]` ```js { @@ -257,7 +257,7 @@ print(res.text) These two allows us to do pagination. Hre page_size is used to specify number of records on a single page and page is used to specify the current page. For example if we want our page_size to be 5 records and we want to fetch data on page 3 here is how we would do it. - `GET /api/product.template/?query={id, name}&page_size=5&page=3` + `GET /rest/product.template/?query={id, name}&page_size=5&page=3` ```js { @@ -282,7 +282,7 @@ print(res.text) This is used to limit the number of results returned on a request regardless of pagination. For example - `GET /api/product.template/?query={id, name}&limit=3` + `GET /rest/product.template/?query={id, name}&limit=3` ```js { @@ -301,13 +301,13 @@ print(res.text) ### Model record: -`GET /api/{model}/{id}` +`GET /rest/{model}/{id}` #### Parameters * **query (optional):** Here query parameter works exactly the same as explained before except it selects fields on a single record. For example - `GET /api/product.template/95/?query={id, name}` + `GET /rest/product.template/95/?query={id, name}` ```js { @@ -327,7 +327,7 @@ print(res.text) This is used to pass data to be posted. For example - `POST /api/product.public.category/` + `POST /rest/product.public.category/` Request Body @@ -345,8 +345,6 @@ print(res.text) ```js { - "jsonrpc": "2.0", - "id": null, "result": 398 } ``` @@ -380,7 +378,7 @@ print(res.text) ### Model records: -`PUT /api/{model}/` +`PUT /rest/{model}/` #### Headers * Content-Type: application/json #### Parameters @@ -392,7 +390,7 @@ print(res.text) This is used to filter data to update. For example - `PUT /api/product.template/` + `PUT /rest/product.template/` Request Body @@ -411,8 +409,6 @@ print(res.text) ```js { - "jsonrpc": "2.0", - "id": null, "result": true } ``` @@ -451,7 +447,7 @@ print(res.text) For example here is how you would update `related_product_ids` which is `many2many` field with PUT operations - `PUT /api/product.template/` + `PUT /rest/product.template/` Request Body @@ -478,15 +474,13 @@ print(res.text) ```js { - "jsonrpc": "2.0", - "id": null, "result": true } ``` ### Model record: -`PUT /api/{model}/{id}` +`PUT /rest/{model}/{id}` #### Headers * Content-Type: application/json #### Parameters @@ -496,7 +490,7 @@ print(res.text) All parameters works the same as explained on previous section, what changes is that here they apply to a single record being updated and we don't have filter parameter because `id` of record to be updated is passed on URL as `{id}`. Example to give us an idea of how this works. -`PUT /api/product.template/95/` +`PUT /rest/product.template/95/` Request Body @@ -518,7 +512,7 @@ Request Body ### Model records: -`DELETE /api/{model}/` +`DELETE /rest/{model}/` #### Parameters * **filter (mandatory):** @@ -539,11 +533,11 @@ Request Body ### Model records: -`DELETE /api/{model}/{id}` +`DELETE /rest/{model}/{id}` #### Parameters This takes no parameter and we don't have filter parameter because `id` of record to be deleted is passed on URL as `{id}`. Example to give us an idea of how this works. -`DELETE /api/product.template/95/` +`DELETE /rest/product.template/95/` Response diff --git a/controllers/controllers.py b/controllers/controllers.py index 74e36f0..786c076 100644 --- a/controllers/controllers.py +++ b/controllers/controllers.py @@ -4,20 +4,18 @@ import logging import requests -from odoo import http, _, exceptions -from odoo.http import request +from odoo import http, exceptions, _ +from odoo.http import request, HttpRequest, Root from .serializers import Serializer from .exceptions import QueryFormatError - _logger = logging.getLogger(__name__) def error_response(error, msg): return { - "jsonrpc": "2.0", - "id": None, + "error": { "code": 200, "message": msg, @@ -32,6 +30,19 @@ def error_response(error, msg): } +ori_get_request = Root.get_request + + +def get_request(self, httprequest): + if httprequest.full_path == '/rest/?': + return HttpRequest(httprequest) + else: + return ori_get_request(self, httprequest) + + +Root.get_request = get_request + + class OdooAPI(http.Controller): @http.route( '/auth/', @@ -57,8 +68,8 @@ def authenticate(self, *args, **post): return res @http.route( - '/object//', - type='json', auth='user', methods=["POST"], csrf=False) + '/rest/object//', + type='http', auth='user', methods=["POST"], csrf=False) def call_model_function(self, model, function, **post): args = [] kwargs = {} @@ -71,8 +82,8 @@ def call_model_function(self, model, function, **post): return result @http.route( - '/object///', - type='json', auth='user', methods=["POST"], csrf=False) + '/rest/object///', + type='http', auth='user', methods=["POST"], csrf=False) def call_obj_function(self, model, rec_id, function, **post): args = [] kwargs = {} @@ -85,7 +96,7 @@ def call_obj_function(self, model, rec_id, function, **post): return result @http.route( - '/api/', + '/rest/', type='http', auth='user', methods=['GET'], csrf=False) def get_model_data(self, model, **params): try: @@ -121,19 +132,19 @@ def get_model_data(self, model, **params): if "page_size" in params: page_size = int(params["page_size"]) count = len(records) - total_page_number = math.ceil(count/page_size) + total_page_number = math.ceil(count / page_size) if "page" in params: current_page = int(params["page"]) else: current_page = 1 # Default page Number - start = page_size*(current_page-1) - stop = current_page*page_size + start = page_size * (current_page - 1) + stop = current_page * page_size records = records[start:stop] - next_page = current_page+1 \ + next_page = current_page + 1 \ if 0 < current_page + 1 <= total_page_number \ else None - prev_page = current_page-1 \ + prev_page = current_page - 1 \ if 0 < current_page - 1 <= total_page_number \ else None @@ -167,7 +178,7 @@ def get_model_data(self, model, **params): ) @http.route( - '/api//', + '/rest//', type='http', auth='user', methods=['GET'], csrf=False) def get_model_rec(self, model, rec_id, **params): try: @@ -207,8 +218,8 @@ def get_model_rec(self, model, rec_id, **params): ) @http.route( - '/api//', - type='json', auth="user", methods=['POST'], csrf=False) + '/rest//', + type='http', auth="user", methods=['POST'], csrf=False) def post_model_data(self, model, **post): try: data = post['data'] @@ -233,8 +244,8 @@ def post_model_data(self, model, **post): # This is for single record update @http.route( - '/api///', - type='json', auth="user", methods=['PUT'], csrf=False) + '/rest///', + type='http', auth="user", methods=['PUT'], csrf=False) def put_model_record(self, model, rec_id, **post): try: data = post['data'] @@ -250,7 +261,7 @@ def put_model_record(self, model, rec_id, **post): if "context" in post: # TODO: Handle error raised by `ensure_one` - rec = model_to_put.with_context(**post["context"])\ + rec = model_to_put.with_context(**post["context"]) \ .browse(rec_id).ensure_one() else: rec = model_to_put.browse(rec_id).ensure_one() @@ -295,8 +306,8 @@ def put_model_record(self, model, rec_id, **post): # This is for bulk update @http.route( - '/api//', - type='json', auth="user", methods=['PUT'], csrf=False) + '/rest//', + type='http', auth="user", methods=['PUT'], csrf=False) def put_model_records(self, model, **post): try: data = post['data'] @@ -314,7 +325,7 @@ def put_model_records(self, model, **post): filters = post["filter"] if "context" in post: - recs = model_to_put.with_context(**post["context"])\ + recs = model_to_put.with_context(**post["context"]) \ .search(filters) else: recs = model_to_put.search(filters) @@ -363,9 +374,9 @@ def put_model_records(self, model, **post): # This is for deleting one record @http.route( - '/api///', + '/rest///', type='http', auth="user", methods=['DELETE'], csrf=False) - def delete_model_record(self, model, rec_id, **post): + def delete_model_record(self, model, rec_id, **post): try: model_to_del_rec = request.env[model] except KeyError as e: @@ -400,7 +411,7 @@ def delete_model_record(self, model, rec_id, **post): # This is for bulk deletion @http.route( - '/api//', + '/rest//', type='http', auth="user", methods=['DELETE'], csrf=False) def delete_model_records(self, model, **post): filters = json.loads(post["filter"]) @@ -438,9 +449,9 @@ def delete_model_records(self, model, **post): ) @http.route( - '/api///', + '/rest///', type='http', auth="user", methods=['GET'], csrf=False) - def get_binary_record(self, model, rec_id, field, **post): + def get_binary_record(self, model, rec_id, field, **post): try: request.env[model] except KeyError as e: From b66694959a730f50fe5a21b80849d342905a6e3c Mon Sep 17 00:00:00 2001 From: jeffery Date: Tue, 8 Jun 2021 17:00:07 +0800 Subject: [PATCH 2/2] fix url in doc --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9d2a634..89fa543 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ cookies = res.cookies # Example 1 # Get users -USERS_URL = 'http://localhost:8069/api/res.users/' +USERS_URL = 'http://localhost:8069/rest/res.users/' # This will take time since it retrives all res.users fields # You can use query param to fetch specific fields @@ -61,7 +61,7 @@ print(res.text) # Example 2 # Get products(assuming you have products in you db) # Here am using query param to fetch only product id and name(This will be faster) -USERS_URL = 'http://localhost:8069/api/product.product/' +USERS_URL = 'http://localhost:8069/rest/product.product/' # Use query param to fetch only id and name params = {'query': '{id, name}'} @@ -89,7 +89,7 @@ print(res.text) This parameter is used to dynamically select fields to include on a response. For example if we want to select `id` and `name` fields from `res.users` model here is how we would do it. - `GET /api/res.users/?query={id, name}` + `GET /rest/res.users/?query={id, name}` ```js { @@ -319,7 +319,7 @@ print(res.text) ## 2. POST -`POST /api/{model}/` +`POST /rest/{model}/` #### Headers * Content-Type: application/json #### Parameters @@ -518,7 +518,7 @@ Request Body This is used to filter data to delete. For example - `DELETE /api/product.template/?filter=[["id", "=", 95]]` + `DELETE /rest/product.template/?filter=[["id", "=", 95]]` Response