用Django ORM实现树状结构
前言
之前看对于用关系数据库实现树状结构的方法就知道一直做自关联的表,但是感觉自关联查询太慢了,最近看到一篇文章,感觉视野开拓了好多,文章:数据库表设计,没有最好只有最适合来自:微信。
下面就针对这里面说的第四种数据结构来实现以下这种树状结构。这样的结构就是牺牲了空间来换取时间,主要就是在查询和删除上快了好多。
环境介绍
IDE我用的pycharm
Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Django 1.11
创建Django project和配置app
从pycharm里面创建Django的project这里面就不多做介绍了,并且创建一个app01
的app,然后目录结构如下:
bogon:django18 hongzhi.wang$ tree .
.
├── app01
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── django18
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── locale
├── manage.py
创建表结构,重写save方法
app01的models.py文件如下:
from django.db import models
# Create your models here.
class MysqlRelation(models.Model):
parent = models.ForeignKey("Mysql", related_name="mysql_parent")
child = models.ForeignKey("Mysql", related_name="mysql_child")
depth = models.IntegerField(default=0)
def __str__(self):
return "%s___%s" % (self.parent, self.child)
class Mysql(models.Model):
name = models.CharField(max_length=30)
is_slave = models.BooleanField(default=False)
master = models.ForeignKey("Mysql", null=True, blank=True)
comment = models.CharField(max_length=100, null=True, blank=True)
def save(self, *args, **kwargs):
super(Mysql, self).save(*args, **kwargs) # Call the "real" save() method.
if self.master:
MysqlRelation.objects.create(
parent=self, child=self, depth=0
).save()
for obj in self.master.mysql_child.all():
MysqlRelation.objects.create(
parent=obj.parent, child=self, depth=obj.depth+1
).save()
def __str__(self):
return self.name
然后python3 manage.py makemigrations; python3 manage.py migrate本文使用的mysql作为例子,因为mysql的主从关系有时候会形成这种树状结构,(其实如果要用这样的结构还需要重写delete方法,因为django默认的就是那种自关联表的删除,这里就先不实现呢,留到以后吧),如果我要实现
mojideMacBook-Pro-2:tmp hongzhi.wang$ tree v1/
v1/
├── v1-1
│ └── v1-1-1
└── v1-2
这样的结构,我的relation表就是这样的:
| parent | child | depth |
|---|---|---|
| v1 | v1 | 0 |
| v1 | v1-1 | 1 |
| v1-1 | v1-1 | 0 |
| v1 | v1-2 | 1 |
| v1-2 | v1-2 | 0 |
| v1 | v1-1-1 | 2 |
| v1-1 | v1-1-1 | 1 |
| v1-1-1 | v1-1-1 | 0 |
使用django admin创建这样的结构
app01下admin.py文件如下:
from django.contrib import admin
# Register your models here.
from .models import Mysql, MysqlRelation
admin.site.register(Mysql)
admin.site.register(MysqlRelation)
使用django admin创建一个树状的关系结构,到这时models的工作已经做好了,下面我们准备用bootstrap-treeview这个前端插件来展示这个树状结构,本文只是以一个root的树为例讲解,多root的以后再说了。
创建html文件
templates下的home.html文件如下:
<!DOCTYPE html>
<html lang="en">
<link href="https://magicbox.bkclouds.cc/static_api/v3/assets/bootstrap-3.3.4/css/bootstrap.min.css" rel="stylesheet">
<script src="https://magicbox.bkclouds.cc/static_api/v3/assets/js/jquery-1.10.2.min.js"></script>
<script src="https://magicbox.bkclouds.cc/static_api/v3/assets/bootstrap-3.3.4/js/bootstrap-treeview.js"></script>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="plugin12_demo1" class="treeview"></div>
<script type="text/javascript">
// 默认状态
var defaultData = [{
text: 'Parent 1',
nodes: [{
text: 'Child 1',
nodes: [{
text: 'Grandchild 1',
nodes :[]
},{
text: 'Grandchild 2',
}]
},{
text: 'Child 2',
}]
},{
text: 'Parent 2',
}
];
$.getJSON("/data", function (data) {
$('#plugin12_demo1').treeview({
data: data
});
}
);
</script>
</body>
</html>
本文直接用的magicbox的static文件,做例子就图省事了,上面的处理AJAX返回的data可以换成defaultData,来看看这个插件的效果。
urls与views配置
主urls.py如下:
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.home), # 返回主页面
url(r'^data', views.data), #返回树状结构的json字符串
]
app01下views.py如下:
from django.shortcuts import render
from . import models
from django.http import JsonResponse
# Create your views here.
def home(request):
return render(request, 'home.html')
def gen_tree(root):
res = []
branches = models.Mysql.objects.filter(master=root)
if branches:
for branch in branches:
item = dict(
text=branch.name,
)
if models.Mysql.objects.filter(master=branch):
item["nodes"] = gen_tree(branch)
res.append(item)
return res
def data(request):
'''
:param request:
:return:
[{
text: 'Parent 1',
nodes:[{
text: 'child 1',
nodes:{}
},{
text: 'child 2',
nodes:{}
}
]
}]
'''
res = []
tree_root = models.Mysql.objects.filter(master__isnull=True).first()
res.append(dict(text=tree_root.name, nodes=gen_tree(tree_root)))
return JsonResponse(res, safe=False)
到现在为止的目录结构:
bogon:django18 hongzhi.wang$ tree .
.
├── app01
│ ├── __init__.py
│ ├── admin.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── __init__.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── db.sqlite3
├── django18
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
└── templates
├── home.html
然后就可以启动django来看看效果了,也可以通过从django admin添加一个节点,然后刷新页面再看看效果。
用Django ORM实现树状结构的更多相关文章
- 树状结构Java模型、层级关系Java模型、上下级关系Java模型与html页面展示
树状结构Java模型.层级关系Java模型.上下级关系Java模型与html页面展示 一.业务原型:公司的组织结构.传销关系网 二.数据库模型 很简单,创建 id 与 pid 关系即可.(pid:pa ...
- 分享使用NPOI导出Excel树状结构的数据,如部门用户菜单权限
大家都知道使用NPOI导出Excel格式数据 很简单,网上一搜,到处都有示例代码. 因为工作的关系,经常会有处理各种数据库数据的场景,其中处理Excel 数据导出,以备客户人员确认数据,场景很常见. ...
- 由简入繁实现Jquery树状结构
在项目中,我们经常会需要一些树状结构的样式来显示层级结构等,比如下图的样式,之前在学.net的时候可以直接拖个服务端控件过来直接使用非常方便.但是利用Jquery的一些插件,也是可以实现这些效果的,比 ...
- php实现树状结构无级分类
php实现树状结构无级分类 ).",'树2-1-1-2')";mysql_query($sql);?>
- Android无限级树状结构
通过对ListView简单的扩展.再封装,即可实现无限层级的树控件TreeView. package cn.asiontang.nleveltreelistview; import android.a ...
- 使用Map辅助拼装树状结构,消除递归调用
目前菜单或其他树状结构在数据库中的存储,多数是以一个parentid作为关联字段,以一维形式存储.使用时全部查询出来,然后在内存中拼装成树状结构.现在主要涉及的是拼装方法的问题. 一般可以进行 递归调 ...
- lua 怎样输出树状结构的table?
为了让游戏前端数据输出更加条理,做了一个简单树状结构来打印数据. ccmlog.lua local function __tostring(value, indent, vmap) local str ...
- js List<Map> 将偏平化的数组转为树状结构并排序
数据格式: [ { "id":"d3e8a9d6-e4c6-4dd8-a94f-07733d3c1b59", "parentId":&quo ...
- 浅谈oracle树状结构层级查询之start with ....connect by prior、level及order by
浅谈oracle树状结构层级查询 oracle树状结构查询即层次递归查询,是sql语句经常用到的,在实际开发中组织结构实现及其层次化实现功能也是经常遇到的,虽然我是一个java程序开发者,我一直觉得只 ...
随机推荐
- 将json转换为数据结构体
主要用到的依赖:(划重点:这个依赖需要加jdk版本号,不加的话用不了,且目前最高是jdk15) (ps: 用于json与其他类型格式转换,JSONObject, JSONArray等来自这个包) &l ...
- Eclipse Debug不能热部署解决
摘要: Eclipse Debug不能热部署代码may be out-of-synch 问题描述:Project通过ant工具编译部署到JBoss下,在使用Eclipse远程调试功... ...
- centos7在vmware上安装后不能连接网络的问题。注意虚拟机向导时选择的操作系统...........
在虚拟机上安装时发现网络不可用 在网上查找解决方案一整理天,各种命令代码偿试 无效. 在贴上发现说 Centos7镜像是64位 ,虚拟机操作系统一定要选择centos64位也是必须的. 最后选择重 ...
- python——元组和字典类型简明理解
元组类型: 元祖创建: 不需要括号可以但是一个元素就当成了字符串类型了 >>> tup1="a"; >>> type(tup1) <cla ...
- tesseract_vs2015工具包使用
在vs中配置tesseract4.0: 新建一个空的控制台程序.并找到下图位置 双击.x64.user出现如下图: 单击VC++目录,将tesseract-2015/include/tesseract ...
- shell脚本可以解决的问题
1.各类监控脚本,文件,内存,磁盘,端口 url 监控报警 2.监控网站目录文件是否被篡改,以及如何恢复 3.如何开发各类服务rsync nginx mysql等启动停止脚本 4.开发mysql主从复 ...
- Azkaban安装及分布式部署(multiple-executor)
参考文章:https://blog.csdn.net/weixin_35852328/article/details/79327996 官网:https://azkaban.readthedocs.i ...
- JRebel 代理激活
1.生成GUID https://www.guidgen.com/ 例:04cfff79-8f45-481c-a858-a5b9590422e7 2.License Server 例: http: ...
- 31_NavLink组件包装优化
简单理解为自定义一个组件并自带样式 import React, {Component} from 'react' import {Switch, Route, Redirect} from 'reac ...
- 计算机系统的通信PPT版本
通信方式 并行传送:一次8位,需要保持各路信号同时到达,距离和速度受限制,成本较高 串行传送:一次1位,距离较远.速率更高,成本较低. {在单片机的通信中,使用的是串行传送,但是数据寄存器里面的是8位 ...