This not an answer but you can say a tutorial example of dynamic view :
modul structur:
->dynamic_view
--> __ini__.py
--> models.py
--> views.xml
--> __manifest__.py
__manifest__.py
:
# -*- coding: utf-8 -*-
{
'name' : 'Dynamic view',
'version' : '1.0',
'summary': 'Tutorial for Dynamic view',
'sequence': 30,
'description': """
This Module is for showing that you can update the code of the view
when it's called and even create new field without having to use python
code at all
""",
'category': 'StackOverFlow',
'depends' : ['base_setup',],
'data': [
'views.xml'
],
'installable': True,
'application': True,
'auto_install': False,
}
__init__.py
:
# -*- coding: utf-8 -*-
from . import models
models.py
:
# -*- coding: utf-8 -*-
from odoo import models, fields, api
class Person(models.Model):
_name = "training.person"
name = fields.Char("Full name")
class Car(models.Model):
_name = "training.car"
name = fields.Char("Car name")
mark_id = fields.Many2one(comodel_name="training.mark", string="Mark")
owner_id = fields.Many2one(comodel_name="training.person", string="Owner")
person_view_id = "dynamic_view.dgapr_form_person"
# here default arch value body in the view contains only
# name field but as we create new mark we add others field
person_view_arch = """
<group>
<field name="name"/>
</group>
"""
class Mark(models.Model):
_name = "training.mark"
name = fields.Char("Mark")
@api.model
def create(self, values):
"""
when we create a category we add one2many field to person view
TODO: when we unlink a category we need to remove the one2many
name of field is : x_mark_{id of deleted record}
"""
rec_id = super(Mark, self).create(values)
o2m_field = {
# fields created using orm method must start with x_
"name": "x_mark_%s"% rec_id.id,
"field_description": "Mark %s" % rec_id.name,
"ttype": "one2many",
"relation": "training.car",
"relation_field": "owner_id",
"stored": True,
"domain": "[('mark_id','=', %s)]"%rec_id.id,
"model_id": self.env.ref("dynamic_view.model_training_person").id,
}
# add on2many field to ir.model.fields
self.env["ir.model.fields"].create(o2m_field)
self.update_arch()
return rec_id
def update_arch(self):
"""
when ever we create or delete a mark record
we need to update the the view to add new one2many field
if we want to hide the one2many field in view that don't have
any record we should create compute field to use attrs features
"""
view_id = self.env.ref(person_view_id)
o2m_fields_ids = self.env['ir.model.fields'].search(
[
('model_id', '=', self.env.ref("dynamic_view.model_training_person").id),
('ttype', 'like', 'one2many'),
('relation_field', 'like', 'owner_id')
])
o2many_arch = ""
for o2m_id in o2m_fields_ids:
o2many_arch = o2many_arch + """
<group col="1" string="%s">
<field name="%s" noloable="1" />
</group>
""" % (o2m_id.field_description, o2m_id.name,)
arch_begin = """
<form>
<sheet>
"""
arch_close = """
</sheet>
</form>
"""
arch_body = person_view_arch + o2many_arch
new_arch = arch_begin + arch_body + arch_close
# update the arch of the view in database
view_id.arch = new_arch
views.xml:
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="dgapr_form_car" model="ir.ui.view">
<field name="name">car.form</field>
<field name="model">training.car</field>
<field name="arch" type="xml">
<form >
<sheet>
<group>
<field name="name"/>
<field name="mark_id"/>
<field name="owner_id"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="dgapr_action_car" model="ir.actions.act_window">
<field name="name">Cars</field>
<field name="res_model">training.car</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_root_training" name="Training"/>
<menuitem id="menu_ch_car" name="Cars" parent="menu_root_training" action="dgapr_action_car"/>
<record id="dgapr_form_person" model="ir.ui.view">
<field name="name">dgapr.form.person</field>
<field name="model">training.person</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="name"/>
</group>
</sheet>
</form>
</field>
</record>
</data>
</odoo>
i found out that you can create field using ORM method even compute field. i think creating a widget is better but good to know that wen can create costum fields .
Hope this helps you
Note i didn't create a menu for person record but you can see the view by clicking on the owner_id in the car form if the new one2many field not shown just refresh the page.