Working with Admin Classes

Using TreeNodeModelAdmin

The easiest way to integrate tree structures into Django’s admin panel is by inheriting from TreeNodeModelAdmin. This base class provides all the necessary functionality for managing hierarchical data.

admin.py:
from django.contrib import admin
from treenode.admin import TreeNodeModelAdmin

from .models import Category

@admin.register(Category)
class CategoryAdmin(TreeNodeModelAdmin):

    # Set the display mode: 'accordion', 'breadcrumbs', or 'indentation'
    treenode_display_mode = TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_ACCORDION
    # treenode_display_mode = TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_BREADCRUMBS

    list_display = ("name",)
    search_fields = ("name",)

The changelist renders the full tree on the initial request and expands or collapses nodes on the client without additional AJAX calls. All nodes for the current changelist page are already in the DOM; the accordion only toggles their visibility.

TreeNode uses _path as the canonical tree order in admin responses and queryset traversal, so nodes are rendered in hierarchical order consistently.

You can choose from three display modes:

  • TREENODE_DISPLAY_MODE_ACCORDION (default) Toggles client-side expand/collapse of already-rendered nodes.
  • TREENODE_DISPLAY_MODE_BREADCRUMBS Displays the tree as a sequence of breadcrumbs, making it easy to navigate.

The accordion mode is always active, and the setting only affects how nodes are displayed.

Note Earlier versions of this page described lazy-loading of children over AJAX. That is not the shipped behavior: the changelist does not lazy-load tree nodes from the server, so the full page is still bounded by Django's standard changelist pagination. Lazy-loading of tree nodes in the changelist is tracked as a separate feature request.

Search Functionality

The search bar helps quickly locate nodes within large trees. As you type, an AJAX request retrieves up to 20 results based on relevance. If you don't find the desired node, keep typing to refine the search until fewer than 20 results remain. The search endpoint is one of the places where the admin does use AJAX; the changelist expand/collapse described above does not.

Working with Forms

Using TreeNodeForm

If you need to customize forms for tree-based models, inherit from TreeNodeForm. It provides:

  • A custom tree widget for selecting parent nodes.
  • Automatic exclusion of self and descendants from the parent selection to prevent circular references.
forms.py:
from treenode.forms import TreeNodeForm
from .models import Category

class CategoryForm(TreeNodeForm):
    """Form for Category model with hierarchical selection."""

    class Meta(TreeNodeForm.Meta):
        model = Category

Key Considerations:

  • This form automatically ensures that a node cannot be its own parent.
  • It uses TreeWidget, a custom hierarchical dropdown for selecting parent nodes.
  • If you need a form for another tree-based model, use the dynamic factory method:
CategoryForm = TreeNodeForm.factory(Category)

This method ensures that the form correctly associates with different tree models dynamically.

Using TreeWidget Widget

The TreeWidget Class

The TreeWidget class is a custom Select2-like widget that enables hierarchical selection in forms.

widgets.py
from django import forms
from treenode.widgets import TreeWidget
from .models import Category

class CategorySelectionForm(forms.Form):
    parent = forms.ModelChoiceField(
        queryset=Category.objects.all(),
        widget=TreeWidget(),
        required=False
    )

Note

  • Customizable Data Source: The data-url attribute can be adjusted to fetch tree data from a custom endpoint.
  • Requires jQuery: The widget relies on AJAX requests, so ensure jQuery is available when using it outside Django’s admin.
  • Dynamically Fetches Data: It loads the tree structure asynchronously, preventing performance issues with large datasets.

If you plan to use this widget in non-admin templates, make sure the necessary JavaScript and CSS files are included:

<link rel="stylesheet" href="/static/treenode/css/tree_widget.css">
<script src="/static/treenode/js/tree_widget.js"></script>

By following these guidelines, you can seamlessly integrate TreeNodeModelAdmin, TreeNodeForm, and TreeWidget into your Django project, ensuring efficient management of hierarchical data.