Enable Dark Mode!
how-to-create-one2many-field-in-the-odoo-16-website.jpg
By: Prayag K

How to Create One2many Field in the Odoo 16 Website

Technical Odoo 16

In Odoo, the one2many field is used to represent a one-to-many relationship between two models. It allows you to create multiple related records in a target model from a source model.

To define an One2Many field in Odoo, you need to specify the target model and the name of the field on the target model that establishes the relationship. 

Here's an example:

from odoo import models, fields

class ParentModel(models.Model):
	_name = 'parent.model'

	child_ids = fields.One2many(comodel_name='child.
      model',inverse_name='parent_id',
      string='Children')

class ChildModel(models.Model):
	_name = 'child.model'

	parent_id = fields.Many2one(comodel_name='parent.model',
    		       string='Parent')
In this example, we have two models: ParentModel and ChildModel. The ParentModel has an One2Many field called child_ids that establishes a relationship with the ChildModel using the parent_id field on the ChildModel.
With this setup, you can link multiple child records to a parent record using the child_ids field. The child_ids field will be displayed as a list of child records on the parent form view.
One2Many Field in Website
It is really helpful to the users to create records inside an one2many field from the website itself. So that the user can easily fill in the table using a website form or table.  
Let's try with an example.
First of all, create two models that have an one2many relation with the other.
from odoo import api, fields, models, _


class WebFormTest(models.Model):
	_name = 'web.form.test'
	_description = 'Web Form Test'

	name = fields.Char(string='Name', required=True)
	data_line_ids = fields.One2many('data.line', 'form_id', 'Data Lines')


class DataLine(models.Model):
	_name = 'data.line'
	_description = 'Data Lines'

	code = fields.Char('Product Code', required=True)
	cost = fields.Float('Cost', required=True)
	form_id = fields.Many2one('web.form.test', 'Form Id', ondelete='cascade', required=True)

Then, if you need to view this in the backend, you can just create the view for this model. 
Now we need to create a website menu.
 <data noupdate="1">
    <record id="create_form" model="website.menu">
        <field name="name">Web Form</field>
        <field name="url">/submit_web_form</field>
        <field name="parent_id" ref="website.main_menu"/>
        <field name="sequence" type="int">100</field>
    </record>
</data>
This will create a new menu on the website. 

How to Create One2many Field in the Odoo 16 Website-cybrosys

Then create a template for the page.

<template id="form_template" name="Form fill">
        	<t t-call="website.layout">
            	<div id="form_temp">
                	<div id="wrap" class="oe_structure oe_empty">
                    	<div class="container">
                        	<form method="post" action="/create/web_form_record">
                            	<div id="form_template">
                                	<input type="hidden" name="csrf_token"
                                       	t-att-value="request.csrf_token()"/>
                                	<div class="form-group">
                                    	<label class="control-label"
                                           	for="name">Name
                                    	</label>
                                    	<input type="text" name="name"
                                           	id="name"
                                           	class="form-control"
                                           	placeholder="Mitchel Admin"
                                           	required="required"/>
                                	</div>
                                	<div class="form-group">
                                    	<div class='row ml-1'
                                         	style="width:99%;">
                                        	<div class="form-group col-12 show_total_project">
                                            	<div class="row s_col_no_resize s_col_no_bgcolor">
                                                	<table class="table table-bordered mt-3 total_project_costs">
                                                    	<thead>
                                                        	<tr>
                                                            	<td>
                                                                	<strong>
                                                                    	Code *
                                                                	</strong>
                                                            	</td>
                                                            	<td>
                                                                	<strong>Cost *
                                                                	</strong>
                                                            	</td>
                                                            	<td width="5%"></td>
                                                        	</tr>
                                                    	</thead>
                                                    	<div class="collapse">
                                                        	<tbody>
                                                            	<tr class="project_cost_line">
                                                                	<td>
                                                                    	<input required="True"
                                                                           	type="text"
                                                                           	class="form-control"
                                                                           	name="expenditure"
                                                                           	placeholder="Enter Code"
                                                                           	id="expenditure"/>
                                                                	</td>
                                                                	<td>
                                                                    	<div class="d-flex">
                                                                        	<span class="mt-2"
                                                                              	style="margin-right: 0.5rem !important;"
                                                                              	t-esc="request.env.company.currency_id.symbol"/>

                                                                        	<input required="True"
                                                                               	placeholder="Enter Cost"
                                                                               	type="number"
                                                                               	class="form-control total_cost"
                                                                               	name="total_cost"
                                                                               	id="total_cost"/>
                                                                    	</div>

                                                                	</td>
                                                                	<td>
                                                                    	<button class="btn fa fa-trash-o remove_line"
                                                                            	style="color: red; padding: 0px; margin-left: -6px; margin-top: 6px;margin-bottom:15px;"
                                                                            	name="delete"
                                                                            	aria-label="Delete row 1"></button>
                                                                	</td>
                                                            	</tr>


                                                            	<tr class="add_extra_project d-none">
                                                                	<td>
                                                                    	<input type="text"
                                                                           	class="form-control"
                                                                           	name="expenditure"
                                                                           	placeholder="Enter Code"
                                                                           	id="expenditure"/>
                                                                	</td>
                                                                	<td>
                                                                    	<div class="d-flex">
                                                                        	<span class="mt-2"
                                                                              	style="margin-right: 0.5rem !important;"
                                                                              	t-esc="request.env.company.currency_id.symbol"/>
                                                                        	<input placeholder="Enter Cost"
                                                                               	type="number"
                                                                               	class="form-control total_cost"
                                                                               	name="total_cost"
                                                                               	id="total_cost"/>
                                                                        	<!--                                                                	<span style="display: block;" class="mt-2">£</span>-->
                                                                    	</div>


                                                                	</td>
                                                                	<td>
                                                                    	<button class="btn fa fa-trash-o remove_line"
                                                                            	style="color: red; padding: 0px; margin-left: -6px; margin-top: 6px;margin-bottom:15px;"
                                                                            	name="delete"
                                                                            	aria-label="Delete row 1"></button>
                                                                	</td>
                                                            	</tr>
                                                        	</tbody>
                                                    	</div>
                                                	</table>
                                            	</div>
                                            	<textarea class="d-none"
                                                      	name="data_line_ids">
                                            	</textarea>
                                            	<button type="button"
                                                    	class="btn btn-info add_total_project button-color"
                                                    	style="float: right; margin-right: -15px;">
                                                	<i class="fa fa-plus"/>
                                            	</button>
                                        	</div>
                                    	</div>
                                	</div>
                                	<div class="clearfix oe_login_buttons">
                                    	<button type="submit"
                                            	class="custom_create btn btn-primary btn-block">
                                        	Create
                                    	</button>
                                	</div>
                            	</div>
                        	</form>
                    	</div>
                	</div>
            	</div>
        	</t>
    	</template>

After creating the template, we need to connect the template and the menu using the controller.

class WebForm(http.Controller):

	@http.route('/submit_web_form', type='http', website=True, auth="public")
	def submit_form(self, **kw):
    		return request.render('web_form.form_template', {})
So this will render the template while clicking the web form menu. Below is an example of the view.

How to Create One2many Field in the Odoo 16 Website-cybrosys

There we can enter the name, and we can add multiple codes and cost just by clicking the plus icon at the bottom.
Here we need some Javascript for website operations like adding extra lines, deleting lines, and for form submission.
Custom.js file
odoo.define('web_form.generic_form', function(require){
	"use strict";
	var publicWidget = require('web.public.widget');
	var core = require('web.core');
	var ajax = require('web.ajax');
	var rpc = require('web.rpc');
	var core = require('web.core');
	var QWeb = core.qweb;
	var _t = core._t;

	publicWidget.registry.generic_form_data = publicWidget.Widget.extend({
    	selector: '#form_template',
    	events: {
       	'click .add_total_project': '_onClickAdd_total_project',
       	'click .remove_line': '_onClickRemove_line',
       	'click .custom_create': '_onClickSubmit',
   	},

   	_onClickSubmit: async function(ev){
        	var self = this;
        	var cost_data = [];
        	var rows = $('.total_project_costs > tbody > tr.project_cost_line');
        	_.each(rows, function(row) {
            	let expenditure = $(row).find('input[name="expenditure"]').val();
            	let total_cost = $(row).find('input[name="total_cost"]').val();
            	console.log(expenditure, total_cost)
            	cost_data.push({
                	'code': expenditure,
                	'cost': total_cost,
            	});
        	});
        	$('textarea[name="data_line_ids"]').val(JSON.stringify(cost_data));

   	},

   	_onClickRemove_line: function(ev){
                	$(this).parent().parent().remove();
    	},

   	_onClickAdd_total_project: function(ev){
            	var $new_row = $('.add_extra_project').clone(true);
            	$new_row.removeClass('d-none');
            	$new_row.removeClass('add_extra_project');
            	$new_row.addClass('project_cost_line');
            	$new_row.insertBefore($('.add_extra_project'));
            	_.each($new_row.find('td'), function(val) {
                	$(val).find('input').attr('required', 'required');
            	});
        	},

	});
});

Here _onClickSubmit function is to pass the cost and code to the controller. _onClickRemove_line function is to remove the line or for the delete button.
And the _onClickAdd_total_project is to add an extra line.

How to Create One2many Field in the Odoo 16 Website-cybrosys

Then we need to create a controller for the form submission.

@http.route('/create/web_form_record', type='http', website=True, auth="public", Methods=['POST'])
def create_form(self, **kw):
data = json.loads(kw['data_line_ids'])
    	val = [(0, 0, line) for line in data]
    	values = {
        	'name': kw['name'],
        	'data_line_ids': val,
    	}
    	form_id = request.env['web.form.test'].sudo().create(values)
    	return request.render('web_form.form_template', {})
This will create a record inside the model. So using this method, we can easily create a record in the backend. We can also include one2many fields in the record using the template so that we can bring the data to the backend and create the record according to our needs.


If you need any assistance in odoo, we are online, please chat with us.



1
Comments

Mohamad Huzaifah

Thank you for the guidance! this helped me a lot!. But im having trouble with the delete line function. It kept on giving me error. File "/usr/lib/python3.10/json/decoder.py", line 355, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 45 (char 44)

29/08/2023

-

12:11PM



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message