To dynamically insert content into a view, you can render a QWeb template to a string, convert it to an etree node, and append it to the view's architecture.
Key technical requirements:
- Use
ir.qweb._render to generate the XML string from a template. - Use
ir.ui.view.postprocess_and_fields to process the new node and retrieve the required model fields. - Merge the new fields into the
res["models"] dictionary to ensure the UI can load the necessary data.
# Helper to merge model fields
def _merge_view_fields(all_models: dict, new_models: dict):
for model, view_fields in new_models.items():
if model in all_models:
all_models[model] = tuple(set(all_models[model]) | set(view_fields))
else:
all_models[model] = tuple(view_fields)
class XXX():
def _add_content(self, params=None):
if params is None: params = {}
str_element = self.env["ir.qweb"]._render("template_id", params)
return etree.fromstring(str_element)
@api.model
def get_view(self, view_id=None, view_type="form", **options):
res = super(xx, self).get_view(view_id=view_id, view_type=view_type, **options)
View = self.env["ir.ui.view"]
if view_type == 'form':
doc = etree.XML(res["arch"])
all_models = res["models"].copy()
for node in doc.xpath("//div[@name='xxxx']"):
if self.env.context.get('context1'):
new_node = self._add_content()
new_arch, new_models = View.postprocess_and_fields(new_node, self._name)
new_node = etree.fromstring(new_arch)
node.append(new_node)
_merge_view_fields(all_models, new_models)
res["arch"] = etree.tostring(doc)
res["models"] = frozendict(all_models)
return res