diff --git a/README.md b/README.md index 234c3ac..a19a5f8 100644 --- a/README.md +++ b/README.md @@ -2389,3 +2389,89 @@ With this blueprint in place, your `__manifest__.py` file ensures your module is As you continue your journey in Odoo development, understanding and crafting this `manifest` file will empower you to create robust, well-defined modules. Just as unit tests safeguard your code, the manifest file declares your module’s identity and ensures it seamlessly integrates into the Odoo world. 🚀 + +--- + +### Chapter 2: The Web Controllers 🌐 + +After mastering the art of module `manifests`, our journey in the Odoo development landscape takes us to another critical aspect— `Web Controllers`. These controllers are the `gatekeepers`, handling incoming `HTTP` requests and directing them to the right `handlers` within the Odoo ecosystem. + +#### The Architects of the Web: Controllers 🏛️ + +Controllers in Odoo are akin to the conductors of an orchestra, ensuring that every request reaches the right endpoint and is processed correctly. They are created by inheriting from the base `Controller` class and defining routes using the `@route()` decorator. + +```python +class MyController(odoo.http.Controller): + @route('/some_url', auth='public') + def handler(self): + return "Hello, World!" +``` + +This simple piece of code sets up a controller that listens to requests at `/some_url` and responds with "Hello, World!" + +#### Extending the Symphony 🎶 + +Just as the Odoo models can be extended, so can the controllers. If you need to modify the behavior of an existing controller, you can `inherit` from it and override its methods. It's important to `re-decorate` these methods with `@route()` to ensure they remain accessible. + +```python +class Extension(MyController): + @route() + def handler(self): + do_before() + return super(Extension, self).handler() +``` + +Without the `@route()` decorator, the method becomes unpublished and inaccessible, much like a conductor without a baton. + +#### Crafting Routes with Precision 🎯 + +The `@route()` decorator is the magic wand that maps URLs to controller methods. It supports various parameters to fine-tune its behavior: + +- **`route`**: Specifies the URL path(s) this method will handle. +- **`type`**: Determines the request type, either `'json'` or `'http'`. +- **`auth`**: Controls the authentication level required (`'user'`, `'public'`, or `'none'`). +- **`methods`**: Lists the HTTP methods (GET, POST, etc.) this route accepts. +- **`csrf`**: Enables or disables CSRF protection. +- **`cors`**: Configures CORS settings for cross-origin requests. + +These parameters allow you to define routes that are as specific or as flexible as needed, ensuring robust and secure handling of requests. + +#### The Unsung Hero: The Request Object 🦸‍♂️ + +At the heart of every HTTP interaction in Odoo is the `request` object. This object wraps around the incoming HTTP request, providing access to deserialized parameters, session management, and more. + +It offers several utilities: + +- **`update_env`**: Changes the current user or context. +- **`csrf_token`**: Generates a CSRF token for security. +- **`get_http_params`**: Extracts key-value pairs from the query string and form data. + +These tools ensure that your controllers can handle requests efficiently and securely. + +#### Crafting Responses with Care 🎁 + +Returning a response in Odoo can be straightforward or complex, depending on your needs. You can return simple strings for HTML responses, or use helpers like `make_json_response()` for JSON data. The `Response` class is versatile, handling everything from cookies to custom headers. + +```python +def make_response(data, headers=None, cookies=None, status=200): + return Response(data, headers=headers, cookies=cookies, status=status) +``` + +This flexibility allows your controllers to respond appropriately to any situation, ensuring a smooth user experience. + +#### Dispatching Requests: The Gatekeepers 🏰 + +Odoo uses `dispatchers` to route and handle different types of requests: + +- **`HttpDispatcher`**: Handles standard HTTP requests. +- **`JsonRPCDispatcher`**: Manages JSON-RPC calls, supporting named parameters and custom context. + +These dispatchers ensure that each request is processed correctly, whether it’s a simple HTTP call or a complex JSON-RPC interaction. + +### Conclusion🕸️ + +`Web controllers` in Odoo are indispensable, acting as the `backbone` of web interactions. By understanding how to create, extend, and manage these controllers, you unlock the full potential of Odoo's web capabilities. + +As we delve deeper into Odoo development, mastering controllers will empower you to build dynamic, responsive, and secure web applications. + +With this knowledge in hand, you're now ready to orchestrate your own symphony of web interactions within the Odoo ecosystem. 🚀 \ No newline at end of file diff --git a/addons/estate/__init__.py b/addons/estate/__init__.py index 5305644..e89927c 100644 --- a/addons/estate/__init__.py +++ b/addons/estate/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- -from . import models \ No newline at end of file +from . import models +from . import controllers \ No newline at end of file diff --git a/addons/estate/controllers/__init__.py b/addons/estate/controllers/__init__.py new file mode 100644 index 0000000..a4f995a --- /dev/null +++ b/addons/estate/controllers/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import estate_property_controller \ No newline at end of file diff --git a/addons/estate/controllers/estate_property_controller.py b/addons/estate/controllers/estate_property_controller.py new file mode 100644 index 0000000..6fe9c0f --- /dev/null +++ b/addons/estate/controllers/estate_property_controller.py @@ -0,0 +1,49 @@ +import json + +from odoo import http +from odoo.http import request, Response + + +class EstatePropertyController(http.Controller): + + @http.route('/estate/properties', type='http', auth='user', methods=['GET'], csrf=True) + def get_properties(self): + properties = request.env['estate.property'].search([]) + property_list = [] + for property in properties: + property_list.append({ + 'name': property.name, + 'living_area': property.living_area, + 'total_area': property.total_area, + 'state': property.state, + # add other fields as necessary + }) + return Response(json.dumps({'properties': property_list}), content_type='application/json', status=200) + + @http.route('/estate/properties/demo', type='http', auth='public', methods=['GET'], csrf=True) + def get_properties_demo(self): + property_list = [{'name': 'Property {}'.format(property_id), 'living_area': property_id * 10, + 'state': 'sold' if property_id % 2 == 0 else 'new'} for property_id in range(3)] + + return Response(json.dumps({'properties': property_list}), content_type='application/json', status=200) + + @http.route('/estate/properties/opendemo', type='http', auth='none', methods=['GET'], csrf=True) + def get_properties_open_demo(self): + property_list = [{'name': 'Property {}'.format(property_id), 'living_area': property_id * 10, + 'state': 'sold' if property_id % 2 == 0 else 'new'} for property_id in range(3)] + + return Response(json.dumps({'properties': property_list}), content_type='application/json', status=200) + + @http.route('/estate/properties/opendemolist', type='http', auth='none', methods=['GET'], csrf=True) + def get_properties_open_demo_list(self): + property_list = [{'name': 'Property {}'.format(property_id), 'living_area': property_id * 10, + 'state': 'sold' if property_id % 2 == 0 else 'new'} for property_id in range(3)] + + # try json no-named datas : list + return Response(json.dumps(property_list), content_type='application/json', status=200) + +class RestrictEstateProperty(EstatePropertyController): + + @http.route(auth='user') + def get_properties_demo(self): + return super().get_properties_demo() diff --git a/addons/estate/demo/estate_property_demo.xml b/addons/estate/demo/estate_property_demo.xml index 1a5bd9b..e27521e 100644 --- a/addons/estate/demo/estate_property_demo.xml +++ b/addons/estate/demo/estate_property_demo.xml @@ -1,6 +1,6 @@ - + Big Villa new A nice and big villa @@ -16,7 +16,7 @@ South - + Trailer home canceled Home in a trailer park @@ -30,7 +30,7 @@ False - + Bangwa home offer_received Home in a trailer park @@ -43,7 +43,6 @@ 4 False - - - \ No newline at end of file + diff --git a/addons/estate/demo/estate_property_offer_demo.xml b/addons/estate/demo/estate_property_offer_demo.xml index a8cefc4..1059179 100644 --- a/addons/estate/demo/estate_property_offer_demo.xml +++ b/addons/estate/demo/estate_property_offer_demo.xml @@ -1,6 +1,6 @@ - + 10000 14 @@ -8,7 +8,7 @@ - + 1500000 14 @@ -16,7 +16,7 @@ - + 1500001 14 diff --git a/docker-compose.yml b/docker-compose.yml index 0d1af4e..847eded 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,7 +20,7 @@ services: restart: always # Commande à exécuter pour démarrer Odoo - command: "-u all -d learning_db --dev xml --limit-time-real=100000" + command: "-i estate -u all -d learning_db --dev xml --limit-time-real=100000" # Montage des volumes pour persister les données volumes: