diff --git a/src/viur/core/prototypes/tree.py b/src/viur/core/prototypes/tree.py index 91d11fbcf..31e8da73c 100644 --- a/src/viur/core/prototypes/tree.py +++ b/src/viur/core/prototypes/tree.py @@ -1054,35 +1054,24 @@ def onCloned(self, skelType: SkelType, skel: SkeletonInstance, src_skel: Skeleto # Helpers - @exposed - def dump( + def get_content( self, parententry: t.Optional[db.Key | int | str] = None, - depth: int = 3, - limit: int = 30, + depth: int = 99, + limit: int = 99, + _level: int = 1, **kwargs - ) -> str: + ) -> t.Dict: """ - Dumps a Tree's content as JSON, based on a parententry. - - This function is very limited in its bounds, and shall only be used for quick retrieval of small tree structures - and for debugging purposes. + Reads the content of a given parententry recursively into a dict. :param parententry: Parententry to dump; If not given, the fuction tries to figure out a single parent entry. - :param depth: Depth to dump children. Can only be a maxiumum of 3. - :param limit: Limit of entries on each level, can be maximum of 30 per level and type. + :param depth: Depth to dump children. + :param limit: Limit of entries on each level. """ if not utils.string.is_prefix(self.render.kind, "json"): raise errors.BadRequest("Can only use this function on JSON-based renders") - current.request.get().response.headers["Content-Type"] = "application/json" - - if depth < 1 or depth > 3: - raise errors.NotAcceptable("'depth' out of bounds") - - if limit < 1 or limit > 30: - raise errors.NotAcceptable("'limit' out of bounds") - if not parententry: repos = self.getAvailableRootNodes(**kwargs) @@ -1094,9 +1083,29 @@ def dump( case _: raise errors.NotAcceptable(f"Missing required parameter {'parententry'!r}") - def query(parententry, _depth: int = 1): - # fetch the nodes - q = self.viewSkel("node").all() + # fetch the nodes + q = self.viewSkel("node").all() + q.mergeExternalFilter(kwargs | {"parententry": parententry}) + + if not (q := self.listFilter(q)): + raise errors.Unauthorized() + + self._apply_default_order(q) + + ret = [] + for skel in q.fetch(limit=limit): + node = self.render.renderSkelValues(skel) + node["_skeltype"] = "node" + + # recurse into children + if _level < depth: + node["_children"] = self.get_content(skel["key"], depth=depth, limit=limit, _level=_level + 1, **kwargs) + + ret.append(node) + + # fetch the leafs (when this is a tree) + if self.leafSkelCls: + q = self.viewSkel("leaf").all() q.mergeExternalFilter(kwargs | {"parententry": parententry}) if not (q := self.listFilter(q)): @@ -1104,35 +1113,43 @@ def query(parententry, _depth: int = 1): self._apply_default_order(q) - ret = [] - for skel in q.fetch(limit=limit): - node = self.render.renderSkelValues(skel) - node["_skeltype"] = "node" + ret += [ + self.render.renderSkelValues(skel) | {"_skeltype": "leaf"} + for skel in q.fetch(limit=limit) + ] - # recurse into children - if _depth < depth: - node["_children"] = query(skel["key"], _depth + 1) + return ret - ret.append(node) + @exposed + def dump( + self, + parententry: t.Optional[db.Key | int | str] = None, + depth: int = 3, + limit: int = 30, + **kwargs + ) -> str: + """ + Dumps a Tree's content as JSON, based on a parententry. - # fetch the leafs (when this is a tree) - if self.leafSkelCls: - q = self.viewSkel("leaf").all() - q.mergeExternalFilter(kwargs | {"parententry": parententry}) + This function is very limited in its bounds, and shall only be used for quick retrieval of small tree structures + and for debugging purposes. - if not (q := self.listFilter(q)): - raise errors.Unauthorized() + :param parententry: Parententry to dump; If not given, the fuction tries to figure out a single parent entry. + :param depth: Depth to dump children. Can only be a maxiumum of 3. + :param limit: Limit of entries on each level, can be maximum of 30 per level and type. + """ + if not utils.string.is_prefix(self.render.kind, "json"): + raise errors.BadRequest("Can only use this function on JSON-based renders") - self._apply_default_order(q) + current.request.get().response.headers["Content-Type"] = "application/json" - ret += [ - self.render.renderSkelValues(skel) | {"_skeltype": "leaf"} - for skel in q.fetch(limit=limit) - ] + if depth < 1 or depth > 3: + raise errors.NotAcceptable("'depth' out of bounds") - return ret + if limit < 1 or limit > 30: + raise errors.NotAcceptable("'limit' out of bounds") - return json.dumps(query(parententry), cls=CustomJsonEncoder) + return json.dumps(self.get_content(parententry, limit=limit, depth=depth, **kwargs), cls=CustomJsonEncoder) Tree.vi = True