In this blog, we are creating Many2many fields in the Odoo customer portal form. To do that, we want a view and a controller. That will be used to select multiple values in our field.
In this picture, we are creating a custom model, custom_field, and creating a controller and static file for adding a JS function and a view for adding XML files.
<?xml version="1.0" encoding="utf-8"?><odoo> <template id="many2many_odoo_blog" inherit_id="portal.portal_my_details_fields"> <xpath expr="//div[hasclass('clearfix')]" position="before"> <lable>Tags</lable> <select class="js-example-basic-multiple col-xl-6 mb-1 new-get_data" multiple="multiple"> <t t-foreach="tags" t-as="tag"> <option t-att-value="tag" t-esc="tag.name"/> </t> </select> </xpath> </template></odoo>
<template id="many2many_odoo_blog" inherit_id="portal.portal_my_details_fields">
This picture will represent the XML file for which we are creating a template and inheriting the default website portal form view for adding our custom-field tags. To do that, provide the parent id as model name.template_id "portal.portal_my_details_fields."
<xpath expr="//div[hasclass('clearfix')]" position="before">
After we can set our filed position via selecting a div and setting position before clearfix div.
<select class="js-example-basic-multiple col-xl-6 mb-1 new-get_data" multiple="multiple">
Then we are adding a selection field, setting the field attribute as "multiple" for selecting multiple values, and setting class js-example-basic-multiple. For adding a JS function for multiple value selection.
<t t-foreach="tags" t-as="tag"> <option t-att-value="tag" t-esc="tag.name"/></t>
The line <t t-foreach="tags" t-as="tag"> is used to iterate through a list of tags and create an option element for each tag. The t-foreach tag takes two arguments: the name of the list to iterate through and the name of the variable to use to store the current tag. The t-att-value attribute is used to set the value of the option element.tag.name variable used to show tag name in the user interface.
odoo.define('custom_field.Many2many_tag', function (require) { var PublicWidget = require('web.public.widget'); var NewData = PublicWidget.Widget.extend({ selector: '.new-get_data', start: function () { $('.js-example-basic-multiple').select2(); }, }); PublicWidget.registry.Many2many_tag = NewData; return NewData; });
Add a JS file and define the corresponding JS. To do that, we are setting "module name. your unique name" and providing aselector.new-get_data for the function select2() will execute only user selects that particular selector.
We can see our field Tags have been created in the customer portal form. Then we want to get values from the backend. To do that, we are importing Customer Portal, overriding the account function, and adding our custom values.
from odoo.addons.portal.controllers.portal import CustomerPortalfrom odoo.http import requestclass CustomerPortal(CustomerPortal): def account(self, redirect=None, **post): values = self._prepare_portal_layout_values() partner = request.env.user.partner_id values.update({ 'error': {}, 'error_message': [], }) if post and request.httprequest.method == 'POST': error, error_message = self.details_form_validate(post) values.update({'error': error, 'error_message': error_message}) values.update(post) if not error: values = {key: post[key] for key in self.MANDATORY_BILLING_FIELDS} values.update( {key: post[key] for key in self.OPTIONAL_BILLING_FIELDS if key in post}) for field in set(['country_id', 'state_id']) & set( values.keys()): try: values[field] = int(values[field]) except: values[field] = False values.update({'zip': values.pop('zipcode', '')}) self.on_account_update(values, partner) partner.sudo().write(values) if redirect: return request.redirect(redirect) return request.redirect('/my/home') countries = request.env['res.country'].sudo().search([]) states = request.env['res.country.state'].sudo().search([]) tags = request.env['crm.tag'].sudo().search([]) values.update({ 'partner': partner, 'countries': countries, 'states': states, 'has_check_vat': hasattr(request.env['res.partner'], 'check_vat'), 'partner_can_edit_vat': partner.can_edit_vat(), 'redirect': redirect, 'page_name': 'my_details', 'tags': tags }) response = request.render("portal.portal_my_details", values) response.headers['X-Frame-Options'] = 'SAMEORIGIN' response.headers['Content-Security-Policy'] = "frame-ancestors 'self'" return response
tags = request.env['crm.tag'].sudo().search([])
tags = request.env['crm.tag'], creates a variable called tags and assigns it to the value of all the tags in the crm.tag.search([]), searches for all the tags in the model.
'tags': tags
Now we can select all "crm.tags" in our Many2Many field.