A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/fabiocaccamo/django-treenode below:

fabiocaccamo/django-treenode: :deciduous_tree: probably the best abstract model/admin for your tree based stuff.

Probably the best abstract model / admin for your tree based stuff.

Make your model class inherit from treenode.models.TreeNodeModel:

from django.db import models

from treenode.models import TreeNodeModel


class Category(TreeNodeModel):

    # the field used to display the model instance
    # default value 'pk'
    treenode_display_field = "name"

    name = models.CharField(max_length=50)

    class Meta(TreeNodeModel.Meta):
        verbose_name = "Category"
        verbose_name_plural = "Categories"

The TreeNodeModel abstract class adds many fields (prefixed with tn_ to prevent direct access) and public methods to your models.

โš ๏ธ If you are extending a model that already has some fields, please ensure that your model existing fields names don't clash with TreeNodeModel public methods/properties names.

Make your model-admin class inherit from treenode.admin.TreeNodeModelAdmin.

from django.contrib import admin

from treenode.admin import TreeNodeModelAdmin
from treenode.forms import TreeNodeForm

from .models import Category


class CategoryAdmin(TreeNodeModelAdmin):

    # set the changelist display mode: 'accordion', 'breadcrumbs' or 'indentation' (default)
    # when changelist results are filtered by a querystring,
    # 'breadcrumbs' mode will be used (to preserve data display integrity)
    treenode_display_mode = TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_ACCORDION
    # treenode_display_mode = TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_BREADCRUMBS
    # treenode_display_mode = TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_INDENTATION

    # use TreeNodeForm to automatically exclude invalid parent choices
    form = TreeNodeForm

admin.site.register(Category, CategoryAdmin)

You can use a custom cache backend by adding a treenode entry to settings.CACHES, otherwise the default cache backend will be used.

CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.filebased.FileBasedCache",
        "LOCATION": "...",
    },
    "treenode": {
        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
    },
}

Delete a node if cascade=True (default behaviour), children and descendants will be deleted too, otherwise children's parent will be set to None (then children become roots):

Delete the whole tree for the current node class:

Get a list with all ancestors (ordered from root to parent):

obj.get_ancestors()
# or
obj.ancestors

Get the ancestors count:

obj.get_ancestors_count()
# or
obj.ancestors_count

Get the ancestors pks list:

obj.get_ancestors_pks()
# or
obj.ancestors_pks

Get the ancestors queryset (ordered from parent to root):

obj.get_ancestors_queryset()

Get the breadcrumbs to current node (included):

obj.get_breadcrumbs(attr=None)
# or
obj.breadcrumbs

Get a list containing all children:

obj.get_children()
# or
obj.children

Get the children count:

obj.get_children_count()
# or
obj.children_count

Get the children pks list:

obj.get_children_pks()
# or
obj.children_pks

Get the children queryset:

obj.get_children_queryset()

Get the node depth (how many levels of descendants):

obj.get_depth()
# or
obj.depth

Get a list containing all descendants:

obj.get_descendants()
# or
obj.descendants

Get the descendants count:

obj.get_descendants_count()
# or
obj.descendants_count

Get the descendants pks list:

obj.get_descendants_pks()
# or
obj.descendants_pks

Get the descendants queryset:

obj.get_descendants_queryset()

Get a n-dimensional dict representing the model tree:

obj.get_descendants_tree()
# or
obj.descendants_tree
get_descendants_tree_display

Get a multiline string representing the model tree:

obj.get_descendants_tree_display()
# or
obj.descendants_tree_display

Get the first child node:

obj.get_first_child()
# or
obj.first_child

Get the node index (index in node.parent.children list):

obj.get_index()
# or
obj.index

Get the last child node:

obj.get_last_child()
# or
obj.last_child

Get the node level (starting from 1):

obj.get_level()
# or
obj.level

Get the order value used for ordering:

obj.get_order()
# or
obj.order

Get the parent node:

obj.get_parent()
# or
obj.parent

Get the parent node pk:

obj.get_parent_pk()
# or
obj.parent_pk

Set the parent node:

obj.set_parent(parent_obj)

Get the node priority:

obj.get_priority()
# or
obj.priority

Set the node priority:

Get the root node for the current node:

obj.get_root()
# or
obj.root

Get the root node pk for the current node:

obj.get_root_pk()
# or
obj.root_pk

Get a list with all root nodes:

cls.get_roots()
# or
cls.roots

Get root nodes queryset:

Get a list with all the siblings:

obj.get_siblings()
# or
obj.siblings

Get the siblings count:

obj.get_siblings_count()
# or
obj.siblings_count

Get the siblings pks list:

obj.get_siblings_pks()
# or
obj.siblings_pks

Get the siblings queryset:

obj.get_siblings_queryset()

Get a n-dimensional dict representing the model tree:

cls.get_tree()
# or
cls.tree

Get a multiline string representing the model tree:

cls.get_tree_display()
# or
cls.tree_display

Return True if the current node is ancestor of target_obj:

obj.is_ancestor_of(target_obj)

Return True if the current node is child of target_obj:

obj.is_child_of(target_obj)

Return True if the current node is descendant of target_obj:

obj.is_descendant_of(target_obj)

Return True if the current node is the first child:

Return True if the current node is the last child:

Return True if the current node is leaf (it has not children):

Return True if the current node is parent of target_obj:

obj.is_parent_of(target_obj)

Return True if the current node is root:

Return True if the current node is root of target_obj:

obj.is_root_of(target_obj)

Return True if the current node is sibling of target_obj:

obj.is_sibling_of(target_obj)

Update tree manually, useful after bulk updates:

To perform bulk operations it is recommended to turn off signals, then triggering the tree update at the end:

from treenode.signals import no_signals

with no_signals():
    # execute custom bulk operations
    pass

# trigger tree update only once
YourModel.update_tree()
Custom tree serialization

How can I serialize a tree using a custom data structure?

This has been discussed here.

# clone repository
git clone https://github.com/fabiocaccamo/django-treenode.git && cd django-treenode

# create virtualenv and activate it
python -m venv venv && . venv/bin/activate

# upgrade pip
python -m pip install --upgrade pip

# install requirements
pip install -r requirements.txt -r requirements-test.txt

# install pre-commit to run formatters and linters
pre-commit install --install-hooks

# run tests
tox
# or
python runtests.py
# or
python -m django test --settings "tests.settings"

Released under MIT License.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4