可能是您基于树的数据结构最佳抽象模型和管理工具。
项目描述
django-treenode
可能是您基于树结构的最佳抽象模型和管理工具。
功能
- 快速 - 无需查询即可获取
ancestors
、children
、descendants
、parent
、root
、siblings
、tree
- 同步 - 内存中的模型实例会自动更新
- 兼容性 - 您可以轻松地将
treenode
添加到现有项目中 - 无依赖
- 易于配置 - 只需扩展抽象模型/模型-admin
- 管理集成 - 优秀的树可视化:手风琴、面包屑或 缩进
缩进(默认) | 面包屑 | 手风琴 |
---|---|---|
安装
- 运行
pip install django-treenode
- 将
treenode
添加到settings.INSTALLED_APPS
- 使您的模型继承自
treenode.models.TreeNodeModel
(以下将描述) - 使您的模型-admin 继承自
treenode.admin.TreeNodeModelAdmin
(以下将描述) - 运行
python manage.py makemigrations
和python manage.py migrate
配置
models.py
使您的模型类继承自 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"
TreeNodeModel
抽象类为您模型添加了许多字段(以 tn_
为前缀,以防止直接访问)和公开方法。
:warning: 如果您正在扩展已具有一些字段的模型,请确保您的模型现有字段名称与 TreeNodeModel
公开的 方法/属性 名称不冲突。
admin.py
使您的模型-admin 类继承自 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)
settings.py
您可以通过在 settings.CACHES
中添加 treenode
条目来使用自定义缓存后端,否则将使用默认缓存后端。
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.filebased.FileBasedCache",
"LOCATION": "...",
},
"treenode": {
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
},
}
使用方法
方法/属性
delete
delete_tree
get_ancestors
get_ancestors_count
get_ancestors_pks
get_ancestors_queryset
get_breadcrumbs
get_children
get_children_count
get_children_pks
get_children_queryset
get_depth
get_descendants
get_descendants_count
get_descendants_pks
get_descendants_queryset
get_descendants_tree
get_descendants_tree_display
get_first_child
get_index
get_last_child
get_level
get_order
get_parent
get_parent_pk
set_parent
get_priority
set_priority
get_root
get_root_pk
get_roots
get_roots_queryset
get_siblings
get_siblings_count
get_siblings_pks
get_siblings_queryset
get_tree
get_tree_display
is_ancestor_of
is_child_of
is_descendant_of
is_first_child
is_last_child
is_leaf
is_parent_of
is_root
is_root_of
is_sibling_of
update_tree
delete
删除节点 如果 cascade=True
(默认行为),则子节点和后代节点也将被删除,否则子节点的父节点将被设置为 None
(然后子节点变为根节点)
obj.delete(cascade=True)
delete_tree
删除当前节点类的整个树
cls.delete_tree()
get_ancestors
获取一个包含所有祖先的 列表(从根到父节点排序)
obj.get_ancestors()
# or
obj.ancestors
get_ancestors_count
获取 祖先数量
obj.get_ancestors_count()
# or
obj.ancestors_count
get_ancestors_pks
获取 祖先 pks 列表
obj.get_ancestors_pks()
# or
obj.ancestors_pks
get_ancestors_queryset
获取 祖先 queryset(从父节点到根节点排序)
obj.get_ancestors_queryset()
get_breadcrumbs
获取到当前节点的 面包屑(包括当前节点)
obj.get_breadcrumbs(attr=None)
# or
obj.breadcrumbs
get_children
获取一个包含所有子节点的 列表
obj.get_children()
# or
obj.children
get_children_count
获取 子节点数量
obj.get_children_count()
# or
obj.children_count
get_children_pks
获取 子节点 pks 列表
obj.get_children_pks()
# or
obj.children_pks
get_children_queryset
获取 子节点 queryset
obj.get_children_queryset()
get_depth
获取 节点深度(后代级别的数量)
obj.get_depth()
# or
obj.depth
get_descendants
获取一个包含所有后代的 列表
obj.get_descendants()
# or
obj.descendants
get_descendants_count
获取 后代数量
obj.get_descendants_count()
# or
obj.descendants_count
get_descendants_pks
获取 后代 pks 列表
obj.get_descendants_pks()
# or
obj.descendants_pks
get_descendants_queryset
获取 后代 queryset
obj.get_descendants_queryset()
get_descendants_tree
获取一个表示 模型树 的多维 dict
obj.get_descendants_tree()
# or
obj.descendants_tree
get_descendants_tree_display
获取一个表示 模型树 的多行 string
obj.get_descendants_tree_display()
# or
obj.descendants_tree_display
get_first_child
获取 第一个子节点
obj.get_first_child()
# or
obj.first_child
get_index
获取 节点索引(节点在其父节点的子节点列表中的索引)
obj.get_index()
# or
obj.index
get_last_child
获取 最后一个子节点
obj.get_last_child()
# or
obj.last_child
get_level
获取 节点级别(从1开始计数)
obj.get_level()
# or
obj.level
get_order
获取用于排序的 排序值
obj.get_order()
# or
obj.order
get_parent
获取 父节点
obj.get_parent()
# or
obj.parent
get_parent_pk
获取 父节点pk
obj.get_parent_pk()
# or
obj.parent_pk
set_parent
设置 父节点
obj.set_parent(parent_obj)
get_priority
获取 节点优先级
obj.get_priority()
# or
obj.priority
set_priority
设置 节点优先级
obj.set_priority(100)
get_root
获取当前节点的 根节点
obj.get_root()
# or
obj.root
get_root_pk
获取当前节点的 根节点pk
obj.get_root_pk()
# or
obj.root_pk
get_roots
获取包含所有根节点的 列表
cls.get_roots()
# or
cls.roots
get_roots_queryset
获取 根节点查询集
cls.get_roots_queryset()
get_siblings
获取包含所有兄弟节点的 列表
obj.get_siblings()
# or
obj.siblings
get_siblings_count
获取兄弟节点的数量
obj.get_siblings_count()
# or
obj.siblings_count
get_siblings_pks
获取兄弟节点的 pks 列表
obj.get_siblings_pks()
# or
obj.siblings_pks
get_siblings_queryset
获取兄弟节点的 查询集
obj.get_siblings_queryset()
get_tree
获取一个表示 模型树 的多维 dict
cls.get_tree()
# or
cls.tree
get_tree_display
获取一个表示 模型树 的多行 string
cls.get_tree_display()
# or
cls.tree_display
is_ancestor_of
如果当前节点是 target_obj 的 祖先,则返回 True
obj.is_ancestor_of(target_obj)
is_child_of
如果当前节点是 target_obj 的 子节点,则返回 True
obj.is_child_of(target_obj)
is_descendant_of
如果当前节点是 target_obj 的 后代,则返回 True
obj.is_descendant_of(target_obj)
is_first_child
如果当前节点是 第一个子节点,则返回 True
obj.is_first_child()
is_last_child
如果当前节点是 最后一个子节点,则返回 True
obj.is_last_child()
is_leaf
如果当前节点是 叶子节点(没有子节点),则返回 True
obj.is_leaf()
is_parent_of
如果当前节点是 target_obj 的 父节点,则返回 True
obj.is_parent_of(target_obj)
is_root
如果当前节点是 根节点,则返回 True
obj.is_root()
is_root_of
如果当前节点是 target_obj 的 根节点,则返回 True
obj.is_root_of(target_obj)
is_sibling_of
如果当前节点是 target_obj 的 兄弟节点,则返回 True
obj.is_sibling_of(target_obj)
update_tree
手动 更新树,在批量更新后非常有用
cls.update_tree()
批量操作
执行批量操作时,建议关闭信号,然后在最后触发树更新
from treenode.signals import no_signals
with no_signals():
# execute custom bulk operations
pass
# trigger tree update only once
YourModel.update_tree()
常见问题解答
自定义树序列化
我该如何使用自定义数据结构来序列化树?
这个问题已在这里进行了讨论。
测试
# 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"
许可证
在 MIT 许可证 下发布。
支持
另请参阅
-
django-admin-interface
- 由管理员本身定制的默认管理员界面。将弹出窗口替换为模态窗口。 🧙 ⚡ -
django-cache-cleaner
- 使用管理员面板或管理命令轻松清除整个缓存或单个缓存。 🧹✨ -
django-colorfield
- 模型中的简单颜色字段,在管理员中有漂亮的颜色选择器。 🎨 -
django-extra-settings
- 使用 django admin 仅通过配置和管理类型化扩展设置。 ⚙️ -
django-maintenance-mode
- 当维护模式开启时,显示503错误页面。 🚧 🛠️ -
django-redirects
- 具有完全控制的重定向。 ↪️ -
python-benedict
- 支持键列表/键路径的字典子类,I/O 快捷方式(base64、csv、json、pickle、plist、查询字符串、toml、xml、yaml)以及许多实用工具。 📘 -
python-codicefiscale
- 编码/解码意大利税号 - codifica/decodifica del Codice Fiscale。 🇮🇹 💳 -
python-fontbro
- 友好的字体操作。 🧢 -
python-fsutil
- 懒惰开发者使用的文件系统实用工具。 🧟♂️
django_treenode-0.22.1.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 0618693ef3e9e150d2bdc0d828fba8335b2fe376a2faed0d1e3310f9fe1db2bc |
|
MD5 | 0acd57adff49f04150fe20258f3d650e |
|
BLAKE2b-256 | 538bd603e79c5408471f32c99ce187efc63a1e1ae40e153753ddf8199df48d92 |
django_treenode-0.22.1-py3-none-any.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 2759300b4560f09bea42aba6a0f11c4b20f6b36dfc484a1f807587a7206bdfe1 |
|
MD5 | b9d6410a1bec3cf369d194ffeaf54985 |
|
BLAKE2b-256 | bb1a359c6ca6c0efbdda65ade6ada98a236d5d679c762d29638e329dad7f84ed |