返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
Django

Implementing Tree-Type Storage and Editing with django-treebeard

Simply inherit the MP_Node configuration for TreeAdmin, enabling drag-and-drop editing of tree nodes. For visualization? Only django-treebeard is usable; others are either discontinued or have subpar functionality. For initializing data? Manual import is required; otherwise, the admin interface doesn’t even have a button—buggy. The API output is just path and depth—it’s more comfortable to implement this yourself.

曦远 (DealiAxy)约 10 分钟
目录9 个章节

Preface

Actually,in many previous projects,I encountered features related to trees. In the past,I always implemented them myself. Later on,many frontend UI component libraries included Tree components,which you could just plug in and use.

However,since we’re using Django,it’s important to make full use of its ecosystem. But after searching for a long time,the only usable option I found was this treebeard. The others have either been discontinued or have very limited functionality—they lack visual tree-editing capabilities.

Could it be that Django has already declined?

Effect

Take this car modification project as an example.

Achieve the following effect, which allows dragging nodes for editing.

image

Installation

Install dependencies

pdm add django-treebeard

Add treebeard to INSTALLED_APPS

Defining a Model

Just inherit from the MP_Node type.

from treebeard.mp_tree import MP_Node

class CaseCategory(MP_Node):
    name = models.CharField('类别名称', max_length=100)
    node_order_by = ['name']

    def __str__(self):
        return '改装类别: {}'.format(self.name)

    class Meta:
        db_table = 'car_case_category'
        verbose_name = '改装类别'
        verbose_name_plural = verbose_name

Configure admin

To implement visual tree editing, you need to inherit from TreeAdmin.

from treebeard.admin import TreeAdmin

@admin.register(CaseCategory)
class CaseCategoryAdmin(TreeAdmin):
    form = movenodeform_factory(CaseCategory)
    list_display = ['name', 'depth']
    search_fields = ['name']

Initializing Data

You can use code to import the initial Tree data.

(In fact, it's because if you don't import the initialization data first, the admin interface won't even show an add button... I guess it's a bug.)

def seed_data_treebeard():
    from apps.car.models import CaseCategory
    get = lambda node_id: CaseCategory.objects.get(pk=node_id)
    root = CaseCategory.add_root(name='车衣')
    node = get(root.pk).add_child(name='亮面/光面')
    node = get(root.pk).add_child(name='磨砂/哑光')
    root = CaseCategory.add_root(name='改色')
    get(root.pk).add_child(name='纯色系')
    get(root.pk).add_child(name='渐变色')
    get(root.pk).add_child(name='定制彩绘')
    root = CaseCategory.add_root(name='改装')
    get(root.pk).add_child(name='轮毂')
    get(root.pk).add_child(name='刹车')
    get(root.pk).add_child(name='避震')
    root = CaseCategory.add_root(name='省心提')

This way, once you open the admin interface, you'll be able to see the data.

Good enough, I guess.

Write an API Endpoint

Then I'll write a simple API endpoint based on django-ninja

(Actually, this code is auto-generated by DjangoStarter)

from typing import List
from django.shortcuts import get_object_or_404
from ninja import Router, ModelSchema
from django_starter.http.response import responses

router = Router(tags=['case_category'])

class CaseCategoryOut(ModelSchema):
    class Meta:
        model = CaseCategory
        fields = ['id', 'path', 'depth', 'numchild', 'name', ]

@router.get('/', response=List[CaseCategoryOut], url_name='car/case_category/list')
def list_items(request):
    qs = CaseCategory.objects.all()
    return qs

The resulting data looks like this (some data omitted)

{
  "code": 200,
  "data": [
    {
      "id": 4,
      "path": "0001",
      "depth": 1,
      "numchild": 3,
      "name": "Color Change"
    },
    {
      "id": 7,
      "path": "00010001",
      "depth": 2,
      "numchild": 0,
      "name": "Custom Airbrush Painting"
    },
    {
      "id": 6,
      "path": "00010002",
      "depth": 2,
      "numchild": 0,
      "name": "Gradient Color"
    }
  ]
}

Summary

Still more comfortable with a self-implemented solution.

But this one is pretty much out of the box too—it's fine for tinkering around in small projects.

References

_EOF_

Implementing Tree-Type Storage and Editing with django-treebeard

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

Django全文检索实现:HayStack-+-Whoosh-+-Jieba

涉及到的工具 haystack是django的开源搜索框架,该框架支持**Solr**, Elasticsearch, Whoosh, **Xapian搜索引擎,不用更改代码,直接切换引擎,减少代码量。 搜索引擎使用Whoosh,这是一个由纯Python实现的全文搜索引擎,没有二进制文件等,比较小巧,配置比较简单,当然性能自然略低。 中文分词Jieba,由于Whoosh自带的是英文分词,对中文的分

2022-08-26 · Django · 约 1 分钟

给Django的Admin添加自定义Action-并移除需要选择对象的限制

前言 不得不说,Django的Admin真的给开发带来很多便利,这不,我又来折腾了,这次是添加自定义的action 这个自定义的Action可以看看官方文档的介绍,很详细,不再赘述。 https://docs.djangoproject.com/en/3.0/ref/contrib/admin/actions/ 界面效果 Django默认的添加完action是要选择下面的对象才能提交的,不过我不需

2022-08-26 · Django · 约 1 分钟

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…

Implementing Tree-Type Storage and Editing with django-treebeard · StarBlog