Django中使用Bootstrap展示树形结构

概述

在企业管理系统中,经常会有树形结构需求,例如:组织结构、权限等等,本文使用Django和Bootstrap Tree View来展示企业组织结构和对应组织的人员。

实现

模型类(models.py)

  1. class Department(models.Model):
  2. name = models.CharField(u‘单位名称‘, max_length=30)
  3. pri = models.IntegerField(u‘序号‘)
  4. desc = models.CharField(u‘备注‘, max_length=100)
  5. parent = models.ForeignKey(‘self‘, blank=True, null=True, related_name=‘children‘, verbose_name=‘上级单位‘)
  6. full_path = models.CharField(u‘全路径‘, max_length=20, blank=True, null=True)
  7. deep_level = models.IntegerField(u‘深度‘, default=0)
  8. def __str__(self):
  9. return self.name
  10. class Meta:
  11. verbose_name = u‘组织结构‘
  12. verbose_name_plural = u‘组织结构‘
  13. class People(models.Model):
  14. PEOPLE_TYPE_CHOICES = (
  15. (‘A‘, u‘公务员‘),
  16. (‘B‘, u‘事业编‘),
  17. (‘C‘, u‘合同工‘),
  18. (‘D‘, u‘临时工‘),
  19. )
  20. user = models.OneToOneField(User)
  21. nickname = models.CharField(u‘昵称‘, max_length=50)
  22. job = models.CharField(u‘职务‘, max_length=50)
  23. job_type = models.CharField(u‘类别‘, choices=PEOPLE_TYPE_CHOICES, max_length=2, default=‘A‘)
  24. department = models.ForeignKey(Department, related_name=‘peoples‘, verbose_name=‘单位‘)
  25. def __str__(self):
  26. return self.nickname
  27. class Meta:
  28. verbose_name = u‘人员‘
  29. verbose_name_plural = u‘人员‘
  30. class TreeNode():
  31. def __init__(self):
  32. self.id = 0
  33. self.text = "Node 1"
  34. self.href = "#node-1"
  35. self.selectable = True
  36. self.state = {
  37. ‘checked‘: True,
  38. ‘disabled‘: True,
  39. ‘expanded‘: True,
  40. ‘selected‘: True,
  41. },
  42. self.tags = [‘available‘],
  43. self.nodes = []
  44. def to_dict(self):
  45. icon = (len(self.nodes) > 0) and ‘glyphicon glyphicon-list-alt‘ or ‘glyphicon glyphicon-user‘
  46. return {
  47. ‘id‘: self.id,
  48. ‘text‘: self.text,
  49. ‘icon‘: icon,
  50. ‘href‘: self.href,
  51. ‘tags‘: [‘1‘],
  52. ‘nodes‘: self.nodes,
  53. }

Department为组织结构,为表示上下级关系,使用了自关联,ForeignKey的第一个参数为self

,为方便上级查找所有的下级,添加related_name=’children’,这样在查询指定单位的下级时候,可以使用:

  1. p = Department.objects.get(parent=None)
  2. children = p.children.all()

来查询所有的下级。

People类为单位人员,我将它关联到Django内建的User,实现User和People的一对一关联,可以在后台管理页面直接编辑People,People类有一个外键,指向Department,同样添加了related_name=’peoples’方便查询。

为显示树状结构,我建立了一个TreeNode类,这个类不需要保存到数据库,它的属性主要供Bootstrap Tree View使用,因为Python的json模块不能直接序列化TreeNode类,所以添加一个to_dict方法,先将TreeNode转化为一个dict。

URL映射(urls.py)

  1. from django.conf.urls import patterns, url
  2. from dept import views as dept_vies
  3. urlpatterns = [
  4. url(r‘^show/$‘, dept_vies.show, name=‘dept_show‘),
  5. url(r‘^tree/$‘, dept_vies.tree, name=‘dept_tree‘),
  6. url(r‘^people/(\d+)$‘, dept_vies.people, name=‘dept_people‘),
  7. ]

视图(views.py)

  1. def get_dept_tree(parents):
  2. ‘‘‘
  3. 根据提供的父节点,迭代出所有的子节点,并用一个dict的列表来表示
  4. :param parents 父节点列表:
  5. :return 返回dict列表:
  6. ‘‘‘
  7. display_tree = []
  8. for p in parents:
  9. node = TreeNode()
  10. node.id = p.id
  11. node.text = p.name
  12. children = p.children.all()
  13. if len(children) > 0:
  14. node.nodes = get_dept_tree(children)
  15. display_tree.append(node.to_dict())
  16. return display_tree
  17. def show(request):
  18. return render(request, "dept/show.html")
  19. def tree(request):
  20. root = Department.objects.get(parent=None)
  21. tree = get_dept_tree([root])
  22. return JsonResponse(tree, safe=False)
  23. def people(request, pk):
  24. dept = Department.objects.get(pk=pk)
  25. peoples = dept.peoples.all()
  26. return render(request, "dept/peoples.html", {‘peoples‘: peoples})

模板类

show.html

  1. {% extends ‘base.html‘ %}
  2. {% block title %}组织结构{% endblock %}
  3. {% block head %}
  4. <link type="text/css" href="/static/css/bootstrap-treeview.min.css">
  5. {% endblock %}
  6. {% block script %}
  7. <script type="text/javascript" src="/static/js/bootstrap-treeview.min.js"></script>
  8. <script type="text/javascript">
  9. $(function () {
  10. $.ajaxSetup({
  11. data: {csrfmiddlewaretoken: ‘{{ csrf_token }}‘ },
  12. });
  13. var tree = $.getJSON("{% url ‘dept_tree‘ %}", ‘‘, function (data) {
  14. $(‘#tree‘).treeview({
  15. data: data,
  16. level: 2,
  17. showTags: true,
  18. onNodeSelected: function (event, node) {
  19. $.post("../people/"+node.id, {}, function(data){
  20. console.log(data);
  21. $("#result").html(data);
  22. })
  23. }
  24. });
  25. });
  26. });
  27. </script>
  28. {% endblock %}
  29. {% block content %}
  30. <hr>
  31. <div class="row">
  32. <div id="tree" class="col-md-3"></div>
  33. <div id="result" class="col-md-9">
  34. sss
  35. </div>
  36. </div>
  37. {% endblock %}

Django 中自带了防止CSRF攻击的功能,GET请求不需要 CSRF 认证,POST 请求需要正确认证才能得到正确的返回结果,如果没有认证,常常会出现下面django csrf token missing or incorrect的错误。最简洁的方法时设置JQuery的ajax属性:

  1. $.ajaxSetup({
  2. data: {csrfmiddlewaretoken: ‘{{ csrf_token }}‘ },
  3. });

Bootstrap Tree View的使用文档见GitHub

people.html

  1. <table class="table table-bordered">
  2. <tr>
  3. <th>姓名</th><th>职务</th><th>类型</th>
  4. </tr>
  5. {% for people in peoples %}
  6. <tr>
  7. <th>{{ people.nickname }}</th>
  8. <th>{{ people.job }}</th>
  9. <th>{{ people.get_job_type_display }}</th>
  10. </tr>
  11. {% empty %}
  12. <tr><th colspan="3">没有人员</th> </tr>
  13. {% endfor %}
  14. </table>

在show.html页面,当点击不同的节点时候,会发出形如“people/1”的ajax请求,返回结果是一段HTML代码,通过JQuery的html()方法动态加载到show.html页面上。

people有一个job_type属性,为一个元组,如果直接使用people.job_type,仅仅会显示A、B、C等结构,如果想显示对应的描述信息,需要使用get_job_type_display。

总结

本文基本实现树形结构的展示、一对多关联查询、数据异步加载等功能,但具体细节还不够完善。

树形结构每个单位右边的角标没有实现,仅仅用了一个固定数字1来占位,设想可以显示单位人数,待完善。

树形结构的查询需要进一步封装,如果要查询根节点下的所有单位,目前只能够多次查询,查询效率不高,考虑使用full_path和deep_level两个冗余字段存储单位的全路径和节点深度,通过startswith来查询所有子节点,如果使用SQL SERVER数据库,可以通过触发器的方式动态修改这两个字段你,使用Django目前还没有较好的办法。

来自为知笔记(Wiz)

时间: 2024-10-25 00:48:11

Django中使用Bootstrap展示树形结构的相关文章

在现在这个社会,你认为软件开发过程中团队模式使用树形结构好还是扁平化结构好?

树形结构:像树一样,有树干(父节点),树叶(子节点)等,将组织机构进行分层,上层管理下层,下层管理下下层.这样的模式优点在于将组织层层细化,条理清晰:缺点在于管理机构太多,另外下级可能不敢违背上级的命令,从而缺乏建设性的意见,是团队项目开发的主要内容掌握在少数人的手中.     扁平化结构:减少管理层级,每个管理层次的管理幅度较大,从而形成管理层次较少的层次结构.这种结构的优点在于信息从下层流通到上层的距离变短,高层了解基层的机会变多,减少了管理者的费用,下级可以有较多的发挥优势的机会,以及提高

django中引入bootstrap

总体的目录结构如下图:mysite 是我创建的一个项目 一.首先在你的项目文件夹下创建一个名为 static 的目录 ,并把下载好的bootstrap目录拷到static目录下. 二.打开settings.py文件,在文件的最后添加如下内容: STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'collectstatic') STATICFILES_DIRS = (os.path.join(BASE_DIR, "static

利用多叉树实现Ext JS中的无限级树形菜单(一种构建多级有序树形结构JSON的方法)

一.问题研究的背景和意义 目前在Web应用程序开发领域,Ext JS框架已经逐渐被广泛使用,它是富客户端开发中出类拔萃的框架之一.在Ext的UI控件中,树形控件无疑是最为常用的控件之一,它用来实现树形结构的菜单.TreeNode用来实现静态的树形菜单,AsyncTreeNode用来实现动态的异步加载树形菜单,后者最为常用,它通过接收服务器端返回来的JSON格式的数据,动态生成树形菜单节点.动态生成树有两种思路:一种是一次性生成全部树节点,另一种是逐级加载树节点(利用AJAX,每次点击节点时查询下

MVC3+EF4.1学习系列(十)----MVC+EF处理树形结构

通过前几篇文章 我们处理了 一对一, 一对多,多对多关系 很好的发挥了ORM框架的做用 但是 少说了一种 树形结构的处理, 而这种树形关系 我们也经常遇到,常见的N级类别的处理, 以及经常有数据与类别挂钩.今天主要写下EF处理树形结构以及 MVC如何展示树形结构. 前面几篇的例子 一直用的是一个例子,内容是连贯的.这篇是完全单独的~ 先来说下工作中会遇到的常见场景 针对这几个场景来处理~ 1.类别 a.类别可以有无限级别 b.类别的最末端 不确定是第几级 某个节点 可以到二级 其他的节点 有可能

设计模式完结(8)-- 组合模式---树形结构的处理

树形结构的处理--组合模式(一) 组合模式为处理树形结构提供了一种较为完美的解决方案,它描述了如何将容器和叶子进行递归组合,使得用户在使用时无须对它们进行区分,可以一致地对待 容器和叶子. 所以:抽象类    叶子类   容器类 abstract class Component { public abstract void add(Component c); //增加成员 public abstract void remove(Component c); //删除成员 public abstra

结构型模式-组合模式(树形结构的处理)

目录 1. 定义 2. 结构 3. 代码实现 4. 透明组合模式与安全组合模式 4.1 透明组合模式 4.1 安全组合模式 5. 优缺点 6. 适用场景 7. 个人理解 参考 树形结构在软件中随处可见,例如操作系统中的目录结构.应用软件中的菜单.办公系统中的公司组织结构等. 组合模式通过一种巧妙的设计方案使得用户可以一致性地处理整个树形结构或者树形结构的一部分,也可以一致性地处理树形结构中的叶子节点(不包含子节点的节点)和容器节点(包含子节点的节点). 1. 定义 组合模式(Composite

使用C#中的DirectorySearcher来获得活动目录中的组织结构与用户等信息,并在展示成树形结构(附源代码)

使用C#中的DirectorySearcher来获得活动目录中的组织结构与用户等信息,并在展示成树形结构(附源代码) 对于C#来说,取得活动目录中的组织结构相对简单,因为其在System.DirectoryServices命名空间中内置了DirectorySearcher的方法,我们可以组合多种过滤方式,来达到取得活动目录中的所有信息,当然,我现在还没有找到可以得到域用户密码的方式 :) 以下是关键片段 1private static SearchResultCollection _ADHelp

VBA读取文件夹下所有文件夹及文件内容,并以树形结构展示

Const TR_LEVEL_MARK = "+"Const TR_COL_INDEX = "A"Const TR_COL_LEVEL = "E"Const TR_COL_NAME = "C"Const TR_COL_COUNT = "D"Const TR_COL_TREE_START = "F"Const TR_ROW_HEIGHT = 23Const TR_COL_LINE_WIDT

Hibernate中,基于Annotation的简单树形结构的实现

在系统设计中,经常用到递归性质的树形结果,比如菜单.多级分类等,一般是在同一个表中定义父子关系实现这种结构. 下面是在Hibernate中,基于Annotation的简单树形结构的实现: 第一步:创建Entity类,并添加注解实现关联关系    ps: 主要是利用@ManyToOne 和 @OneToMany 配置在同一个Entity类中实现树形递归的结构.hibernate注解形式比在xml配置更加简洁 TreeNode.java 1 package com.hfut.hibernate; 2