Skip to content

Commit 8d2b860

Browse files
committed
Import the TreeAdmin from feincms3
1 parent 090a298 commit 8d2b860

File tree

12 files changed

+751
-83
lines changed

12 files changed

+751
-83
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
fail-fast: false
1414
max-parallel: 5
1515
matrix:
16-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
16+
python-version: ["3.8", "3.10", "3.11", "3.12", "3.13"]
1717

1818
services:
1919
mariadb:
@@ -69,7 +69,7 @@ jobs:
6969
fail-fast: false
7070
max-parallel: 5
7171
matrix:
72-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
72+
python-version: ["3.8", "3.10", "3.11", "3.12", "3.13"]
7373

7474
services:
7575
postgres:
@@ -125,7 +125,7 @@ jobs:
125125
fail-fast: false
126126
max-parallel: 5
127127
matrix:
128-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
128+
python-version: ["3.8", "3.10", "3.11", "3.12", "3.13"]
129129

130130
steps:
131131
- uses: actions/checkout@v4

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ Next version
77
- Added the missing ``FieldDoesNotExist`` import. Thanks Kircheneer.
88
- Fixed all errors reported by pre-commit and started running hooks
99
automatically.
10+
- Added ``TreeAdmin`` class for Django admin with intuitive tree
11+
management, node moving capabilities, and support for both positioned and
12+
unpositioned trees. Requires ``django-js-asset`` which is included in the new
13+
``admin`` extra.
1014

1115

1216
0.20 (2025-06-11)

README.rst

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,3 +468,56 @@ Example with depth-limited queryset:
468468

469469
This is particularly useful for creating expandable tree interfaces or
470470
rendering only portions of large trees for performance.
471+
472+
473+
Django Admin Integration
474+
~~~~~~~~~~~~~~~~~~~~~~~~
475+
476+
django-tree-queries includes a ``TreeAdmin`` class for Django's admin interface
477+
that provides an intuitive tree management experience with drag-and-drop style
478+
node moving capabilities.
479+
480+
Installation
481+
------------
482+
483+
To use the admin functionality, install with the ``admin`` extra:
484+
485+
.. code-block:: bash
486+
487+
pip install django-tree-queries[admin]
488+
489+
Usage
490+
-----
491+
492+
.. code-block:: python
493+
494+
from django.contrib import admin
495+
from tree_queries.admin import TreeAdmin
496+
from .models import Category
497+
498+
@admin.register(Category)
499+
class CategoryAdmin(TreeAdmin):
500+
list_display = [*TreeAdmin.list_display, "name", "is_active"]
501+
position_field = "position" # Optional: field used for sibling ordering
502+
503+
The ``TreeAdmin`` provides:
504+
505+
- **Tree visualization**: Nodes are displayed with indentation and visual tree structure
506+
- **Collapsible nodes**: Click to expand/collapse branches for better navigation
507+
- **Node moving**: Cut and paste nodes to reorganize the tree structure
508+
- **Flexible ordering**: Supports both ordered (with position field) and unordered trees
509+
- **Root moves**: Direct "move to root" buttons for trees without sibling ordering
510+
511+
**Configuration:**
512+
513+
- Set ``position_field`` to the field name used for positioning siblings (e.g., ``"position"``, ``"order"``)
514+
- Leave ``position_field = None`` for trees positioned by other criteria (pk, name, etc.)
515+
- The admin automatically adapts its interface based on whether positioning is controllable
516+
517+
**Required list_display columns:**
518+
519+
- ``collapse_column``: Shows expand/collapse toggles
520+
- ``indented_title``: Displays the tree structure with indentation
521+
- ``move_column``: Provides move controls (cut, paste, move-to-root)
522+
523+
These are included by default in ``TreeAdmin.list_display``.

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,14 @@ classifiers = [
3333
dynamic = [
3434
"version",
3535
]
36+
dependencies = [
37+
]
38+
optional-dependencies.admin = [
39+
"django-js-asset",
40+
]
3641
optional-dependencies.tests = [
3742
"coverage",
43+
"django-js-asset",
3844
"pytest",
3945
"pytest-cov",
4046
"pytest-django",

tests/testapp/admin.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
from django.contrib import admin
22

33
from testapp import models
4+
from tree_queries.admin import TreeAdmin
45

56

67
@admin.register(models.Model)
7-
class ModelAdmin(admin.ModelAdmin):
8-
list_display = ("name",)
8+
class ModelAdmin(TreeAdmin):
9+
position_field = "order"
10+
list_display = [*TreeAdmin.list_display, "name"]
11+
12+
13+
@admin.register(models.UnorderedModel)
14+
class UnorderedModelAdmin(TreeAdmin):
15+
list_display = [*TreeAdmin.list_display, "name"]
16+
17+
18+
@admin.register(models.StringOrderedModel)
19+
class StringOrderedModelAdmin(TreeAdmin):
20+
list_display = [*TreeAdmin.list_display, "name"]

tests/testapp/settings.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@
2222
}
2323

2424
INSTALLED_APPS = [
25-
# "django.contrib.auth",
26-
# "django.contrib.admin",
27-
# "django.contrib.contenttypes",
28-
# "django.contrib.sessions",
29-
# "django.contrib.staticfiles",
30-
# "django.contrib.messages",
25+
"django.contrib.auth",
26+
"django.contrib.admin",
27+
"django.contrib.contenttypes",
28+
"django.contrib.sessions",
29+
"django.contrib.staticfiles",
30+
"django.contrib.messages",
3131
"testapp",
3232
"tree_queries",
3333
]

0 commit comments

Comments
 (0)