Allows the viewing of hierarchical models (i.e. parent-child relationships) directly in a tree view. Simply add the recursive attribute to the tree tag with `recursive="1"` or `recursive="true"` or `recursive="True"`. Parent-child field is autodetected from the model based on the _parent_name field which is standard in the Odoo ORM. Currently there is no option for expanding all children, but this may be added in future versions.
59 lines
2 KiB
Python
59 lines
2 KiB
Python
import logging
|
|
import os
|
|
from lxml import etree
|
|
from odoo.tools import misc, view_validation
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
_tree_validator = None
|
|
RNG_NS = "http://relaxng.org/ns/structure/1.0"
|
|
|
|
|
|
def schema_tree(arch, **kwargs):
|
|
global _tree_validator
|
|
|
|
if _tree_validator is None:
|
|
try:
|
|
# Load and parse the existing schema file
|
|
schema_path = os.path.join("addons", "base", "rng", "tree_view.rng")
|
|
with misc.file_open(schema_path) as f:
|
|
rng_doc = etree.parse(f)
|
|
|
|
# Find the `tree` definition in the parsed document
|
|
tree_define = rng_doc.find(".//{%s}define[@name='tree']" % RNG_NS)
|
|
if tree_define is not None:
|
|
# Add the `recursive` attribute as an optional attribute in the `tree` definition
|
|
tree_elem = tree_define.find(".//{%s}element[@name='tree']" % RNG_NS)
|
|
if tree_elem is not None:
|
|
optional_attr = etree.SubElement(
|
|
tree_elem,
|
|
_tag="{%s}optional" % RNG_NS,
|
|
)
|
|
recursive_attr = etree.SubElement(
|
|
optional_attr,
|
|
_tag="{%s}attribute" % RNG_NS,
|
|
name="recursive",
|
|
)
|
|
|
|
# Create RelaxNG validator from the modified schema
|
|
_tree_validator = etree.RelaxNG(rng_doc)
|
|
|
|
except (etree.RelaxNGParseError, etree.XMLSyntaxError) as e:
|
|
_logger.error("Error parsing RelaxNG schema: %s", e.error_log)
|
|
return False
|
|
except Exception as e:
|
|
_logger.error("General error loading RelaxNG schema: %s", e)
|
|
return False
|
|
|
|
# Validate the XML arch
|
|
if _tree_validator.validate(arch):
|
|
return True
|
|
|
|
# Log validation errors
|
|
for error in _tree_validator.error_log:
|
|
_logger.error("Validation error: %s", error)
|
|
return False
|
|
|
|
|
|
# Register the validator with Odoo's view validation
|
|
view_validation._validators.update(tree=[schema_tree])
|