Describs the possible directions for the


An abstract AdjacencyList implementation representing a Tree.


A base class for collections working with AdjacencyList.


sort_siblings(→ None)

Sorts the siblings by the given key, writing the order to the

numeric_priority(→ int | None)

Transforms a alphabetical order into a numeric value that can be

Module Contents

class core.orm.abstract.adjacency_list.MoveDirection(*args, **kwds)[source]

Bases: enum.Enum

Describs the possible directions for the AdjacencyListCollection.move() method.

above = 1[source]
below = 2[source]
core.orm.abstract.adjacency_list.sort_siblings(siblings: Sequence[_L], key: Callable[[_L], SupportsRichComparison], reverse: bool = False) None[source]

Sorts the siblings by the given key, writing the order to the database.

class core.orm.abstract.adjacency_list.AdjacencyList(title: str, parent: Self | None = None, **kwargs: Any)[source]

Bases: onegov.core.orm.Base

An abstract AdjacencyList implementation representing a Tree.

__abstract__ = True[source]
id: Column[int][source]
property parent_id: Column[int | None][source]
name: Column[str][source]
title: Column[str][source]
type: Column[str][source]
property children: relationship[list[Self]][source]
order: Column[int][source]
property __mapper_args__[source]
property __table_args__[source]
validate_name(key: None, name: str) str[source]
property sort_key: Callable[[Self], SupportsRichComparison][source]

The sort key used for sorting the siblings if the title changes.

property sort_on_title_change: Callable[[Self, str], None][source]

Makes sure the A-Z sorting is kept when a title changes.

property root: AdjacencyList[source]

Returns the root of this item.

property ancestors: Iterator[AdjacencyList][source]

Returns all ancestors of this item.

property siblings: Query[Self][source]

Returns a query that includes all siblings, including the item itself.

property path: str[source]

Returns the path of this item.

absorb() str[source]

Alias for path. This is a convenience feature for Morepath if a path is absorbed.


__repr__() str[source]

Return repr(self).

class core.orm.abstract.adjacency_list.AdjacencyListCollection(session: sqlalchemy.orm.session.Session)[source]

Bases: Generic[_L]

A base class for collections working with AdjacencyList.

property __listclass__: type[_L][source]

The list class this collection handles. Must inherit from AdjacencyList.

static sort_key(item: _L) _typeshed.SupportsRichComparison[source]

The sort key with which the items are sorted into their siblings.

query(ordered: bool = True) Query[_L][source]

Returns a query using AdjacencyListCollection.__listclass__.

property roots: list[_L][source]

Returns the root elements.

by_id(item_id: int) _L | None[source]

Takes the given page id and returns the page. Try to keep this id away from the public. It’s not a security problem if it leaks, but it’s not something the public can necessarly count on.

If possible use the path instead.

by_path(path: str, ensure_type: str | None = None) _L | None[source]

Takes a path and returns the page associated with it.

For example, given this hierarchy:

Page(name='documents', id=0, parent_id=None)
    Page(name='readme', id=1, parent_id=0)
    Page(name='license', id=2, parent_id=0)

The following query would return the Page with the name ‘license’:


Slashes at the beginning or end are ignored, so the above is equal to:


Lookups by path are currently quite wasteful. To get the root of a page nested deeply one has to walk the ascendants of the page one by one, triggering a number of queries.

Should this actually become a bottleneck (it might be fine), we should probably implement a materialized view that is updated whenever a page changes.


< postgres-tree-shootout-part-1%3A-introduction./>

< postgres-tree-shootout-part-2%3A-adjacency-list-using-ctes/>

get_unique_child_name(name: str, parent: _L | None) str[source]

Takes the given name or title, normalizes it and makes sure that it’s unique among the siblings of the item.

This is achieved by adding numbers at the end if there are overlaps.

For example, root becomes root-1 if root exists. root-2 if root-1 exists and so on.

add(parent: _L | None, title: str, name: str | None = None, type: str | None = None, **kwargs: Any) _L[source]

Adds a child to the given parent.

add_root(title: str, name: str | None = None, **kwargs: Any) _L[source]
add_or_get(parent: _L | None, title: str, name: str | None = None, **kwargs: Any) _L[source]
add_or_get_root(title: str, name: str | None = None, **kwargs: Any) _L[source]
delete(item: _L) None[source]

Deletes the given item and all it’s desecendants!.

move_above(subject: _L, target: _L) None[source]
move_below(subject: _L, target: _L) None[source]
move(subject: _L, target: _L, direction: MoveDirection) None[source]

Takes the given subject and moves it somehwere in relation to the target.


The item to be moved.


The item above which or below which the subject is moved.


The direction relative to the target. Either MoveDirection.above if the subject should be moved above the target, or MoveDirection.below if the subject should be moved below the target.

core.orm.abstract.adjacency_list.ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[source]
core.orm.abstract.adjacency_list.numeric_priority(string: str | None, max_len: int = 4) int | None[source]

Transforms a alphabetical order into a numeric value that can be used for the ordering of the siblings. German Umlaute and also numbers are supported.