or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

admin-integration.mdforms-ui.mdindex.mdtree-models.mdtree-navigation.mdtree-operations.mdutilities.md
tile.json

tessl/pypi-django-treebeard

Efficient tree implementations for Django models providing three different tree algorithms with unified API

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/django-treebeard@4.7.x

To install, run

npx @tessl/cli install tessl/pypi-django-treebeard@4.7.0

index.mddocs/

Django Treebeard

Django Treebeard provides efficient tree data structure implementations for Django models. It offers three different tree algorithms (Adjacency List, Materialized Path, and Nested Sets) with a unified API, enabling developers to store and manipulate hierarchical data with optimized database operations.

Package Information

  • Package Name: django-treebeard
  • Language: Python
  • Installation: pip install django-treebeard
  • Django Support: Django 3.2, 4.1, 4.2, 5.0
  • Python Support: Python 3.8 - 3.12
  • Database Support: PostgreSQL, MySQL, SQLite, SQL Server

Core Imports

from treebeard.al_tree import AL_Node
from treebeard.mp_tree import MP_Node  
from treebeard.ns_tree import NS_Node

For admin integration:

from treebeard.admin import TreeAdmin

For forms:

from treebeard.forms import MoveNodeForm, movenodeform_factory

For exceptions:

from treebeard.exceptions import (
    InvalidPosition, InvalidMoveToDescendant, 
    NodeAlreadySaved, MissingNodeOrderBy, PathOverflow
)

Basic Usage

from django.db import models
from treebeard.mp_tree import MP_Node

class Category(MP_Node):
    name = models.CharField(max_length=50)
    
    node_order_by = ['name']

# Create root nodes
root1 = Category.add_root(name='Electronics')
root2 = Category.add_root(name='Books')

# Add children
phones = root1.add_child(name='Phones')
laptops = root1.add_child(name='Laptops')

# Add grandchildren
smartphones = phones.add_child(name='Smartphones')
tablets = phones.add_child(name='Tablets')

# Navigate the tree
print(root1.get_children())           # [phones, laptops]
print(phones.get_parent())            # root1
print(root1.get_descendants())        # [phones, laptops, smartphones, tablets]
print(smartphones.get_ancestors())    # [root1, phones]

# Move nodes
smartphones.move(laptops, pos='first-child')

# Bulk operations
data = [
    {'name': 'Science'},
    {'name': 'Fiction', 'children': [
        {'name': 'Sci-Fi'},
        {'name': 'Fantasy'}
    ]}
]
Category.load_bulk(data, parent=root2)

Architecture

Django Treebeard provides three tree implementations, each optimized for different use cases:

Tree Implementations

  • Adjacency List (AL_Node): Traditional parent-child references, best for small trees with frequent writes
  • Materialized Path (MP_Node): Path-based storage, excellent for read-heavy workloads and large trees
  • Nested Sets (NS_Node): Left/right boundary model, optimal for read operations and subtree queries

Unified API

All implementations inherit from the abstract Node class, providing consistent methods for tree operations regardless of the underlying algorithm.

Django Integration

  • Model inheritance for easy setup
  • Admin interface with drag-and-drop support
  • Form classes for node manipulation
  • Template tags for rendering trees

Capabilities

Tree Implementation Models

Base classes for creating tree models using different algorithms, each with specific performance characteristics and database storage patterns.

class AL_Node(Node):
    """Adjacency List implementation"""
    # Requires: parent (ForeignKey), sib_order (PositiveIntegerField)

class MP_Node(Node):
    """Materialized Path implementation"""
    path = models.CharField(max_length=255, unique=True)
    depth = models.PositiveIntegerField()
    numchild = models.PositiveIntegerField()

class NS_Node(Node):
    """Nested Sets implementation"""
    lft = models.PositiveIntegerField(db_index=True)
    rgt = models.PositiveIntegerField(db_index=True)
    tree_id = models.PositiveIntegerField(db_index=True)
    depth = models.PositiveIntegerField(db_index=True)

Tree Implementation Models

Tree Operations

Core methods for creating, reading, updating, and deleting tree nodes, including bulk operations and tree structure manipulation.

# Class methods
@classmethod
def add_root(**kwargs): ...
@classmethod
def load_bulk(bulk_data, parent=None, keep_ids=False): ...
@classmethod
def get_root_nodes(): ...

# Instance methods  
def add_child(**kwargs): ...
def add_sibling(pos=None, **kwargs): ...
def move(target, pos=None): ...
def delete(): ...

Tree Operations

Tree Navigation

Methods for traversing tree structures, getting related nodes, and querying tree relationships.

def get_parent(update=False): ...
def get_children(): ...
def get_siblings(): ...
def get_ancestors(): ...
def get_descendants(): ...
def get_root(): ...
def is_child_of(node): ...
def is_descendant_of(node): ...

Tree Navigation

Django Admin Integration

Admin classes and utilities for managing tree structures through Django's admin interface with drag-and-drop functionality.

class TreeAdmin(admin.ModelAdmin):
    def changelist_view(request, extra_context=None): ...
    def move_node(request): ...

def admin_factory(form_class): ...

Admin Integration

Forms and UI

Form classes for tree manipulation in Django applications, including move operations and tree rendering.

class MoveNodeForm(forms.ModelForm):
    def save(commit=True): ...
    def mk_dropdown_tree(model, for_node=None): ...

def movenodeform_factory(model, form=MoveNodeForm, **kwargs): ...

Forms and UI

Utility Functions

Helper functions for number base conversion, tree validation, and database-specific operations.

# Number conversion for MP trees
def int2str(num, radix=10, alphabet=BASE85): ...
def str2int(num, radix=10, alphabet=BASE85): ...

# Tree validation
@classmethod  
def find_problems(): ...
@classmethod
def fix_tree(): ...

Utility Functions

Exception Handling

Django Treebeard defines specific exceptions for tree operations:

class InvalidPosition(Exception):
    """Raised when passing an invalid pos value"""

class InvalidMoveToDescendant(Exception):
    """Raised when attempting to move a node to one of its descendants"""
    
class NodeAlreadySaved(Exception):
    """Raised when attempting to add a node which is already saved"""
    
class MissingNodeOrderBy(Exception):
    """Raised when node_order_by attribute is missing but required"""
    
class PathOverflow(Exception):
    """Raised when no more space available in MP tree path"""

Configuration

Node Ordering

Set node_order_by on your model class to enable automatic node ordering:

class Category(MP_Node):
    name = models.CharField(max_length=50)
    created_date = models.DateTimeField(auto_now_add=True)
    
    node_order_by = ['name', 'created_date']

MP_Node Configuration

Materialized Path nodes support additional configuration:

class Category(MP_Node):
    name = models.CharField(max_length=50)
    
    steplen = 4  # Path step length
    alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'  # Path encoding alphabet
    gap = 10     # Gap between path values for insertions

Performance Considerations

  • AL_Node: Best for small trees, frequent writes, simple parent-child queries
  • MP_Node: Excellent for large trees, read-heavy workloads, path-based queries
  • NS_Node: Optimal for complex tree queries, subtree operations, minimal writes

Choose the implementation based on your specific use case and performance requirements.