ETJava Beta | Java    注册   登录
  • 搜索:
  • 使用django-treebeard实现树类型存储与编辑

    发表于      阅读(1)     博客类别:Crawler     转自:https://www.cnblogs.com/deali/p/18342233
    如有侵权 请联系我们删除  (页面底部联系我们)  

    前言

    其实之前做很多项目都有遇到跟树相关的功能,以前都是自己实现的,然后前端很多UI组件库都有Tree组件,套上去就可以用。

    不过既然用 Django 了,还是得充分发挥一下生态的优势,但是我找了半天,也就这个 treebeard 能用,其他要不停更了要不就功能很拉,没有可视化编辑树的功能。

    难道Django已经没落了?

    效果

    以这个汽车改装项目为例

    实现以下效果,可以拖动节点进行编辑

    image

    安装

    安装依赖

    pdm add django-treebeard
    

    treebeard 添加到 INSTALLED_APPS

    定义model

    继承 MP_Node 类型就可以

    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
    

    配置 admin

    需要继承 TreeAdmin 才能实现可视化的树编辑

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

    初始化数据

    可以使用代码把初始化的Tree数据导入

    (事实上是因为不先导入初始化数据,admin界面连个添加按钮都没有……估计是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='省心提')
    

    这样打开admin界面就可以看到了

    算是能用吧

    写个接口

    然后我再写个简单的接口,基于 django-ninja

    (实际上这些代码是 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
    

    结果出来的数据是这样(省略部分数据)

    {
      "code": 200,
      "data": [
        {
          "id": 4,
          "path": "0001",
          "depth": 1,
          "numchild": 3,
          "name": "改色"
        },
        {
          "id": 7,
          "path": "00010001",
          "depth": 2,
          "numchild": 0,
          "name": "定制彩绘"
        },
        {
          "id": 6,
          "path": "00010002",
          "depth": 2,
          "numchild": 0,
          "name": "渐变色"
        }
      ]
    }
    

    小结

    还是自己实现的舒服。

    不过这个也算是开箱即用了,小项目的话随便搞搞还是可以的。

    参考资料