python生成树状图_Python将数据库的父子关系表画成树形结构

如何像下图一样将关系型数据库的上下级关系画成树形图

1151103-20170611183236278-746334275.png

1151103-20170611183440012-853487755.png

1151103-20170611183258184-1902654022.png

测试数据准备

为了程序的通用性,也方便进行验证,本例采用最通用的sql写法,数据库采用SQLiter3, 如果你的数据库是ORACLE, MS-SQL, MYSQL,不用修改任何代码,只需要在调用的时候传入相应的db连接即可

defsampledata():

db=sqlite3.connect('dbname.db')

cur=db.cursor()

cur.execute("create table if not exists relation(mother, child)");

cur.execute("INSERT INTO relation(mother, child) VALUES('1000', '1100')");

cur.execute("INSERT INTO relation(mother, child) VALUES('1000', '1200')");

cur.execute("INSERT INTO relation(mother, child) VALUES('1000', '1300')");

cur.execute("INSERT INTO relation(mother, child) VALUES('1000', '1400')");

cur.execute("INSERT INTO relation(mother, child) VALUES('1200', '1210')");

cur.execute("INSERT INTO relation(mother, child) VALUES('1200', '1220')");

cur.execute("INSERT INTO relation(mother, child) VALUES('1200', '1230')");

cur.execute("INSERT INTO relation(mother, child) VALUES('1220', '1221')");

cur.execute("INSERT INTO relation(mother, child) VALUES('1220', '1222')");

db.commit();

看起来是这样的

1151103-20170611180012465-230081546.png

程序编写

节点信息类(相当于C/C++里面的结构体)

value就是当前节点的值

isleaf记录的是当前节点是否是叶子节点

leafcounts记录的是当前节点下面有多少个叶子节点,这个主要是为了在排版的时候知道占用多宽,

maxlevel记录的是当前节点下面最深的深度是多少,这个主要是为了在排版的时候知道生成多长的图片

classdecisionnode:def __init__(self, value, isleaf=False, leafcounts=0, maxlevel=1):

self.childs=[]

self.value=value

self.isleaf=isleaf

self.leafcounts=leafcounts

self.maxlevel=maxleveldefaddchild(self, child):

self.childs.append(child)

关系树类编写

gentree 方法用于生成整棵树,需要传值:db:数据库连接,mathervalue:根节点的数值 tablename:数据库表名 childcol:子节点在表中的对应的字段名称 mothercol:上级节点在表中的字段名称

draweachnode 方法用于化每个节点的值和两个节点之间的连线

drawTree 方法用于画整棵树,它会调用draweachnode然后利用draweachnode的递归画完整棵树

classRelationTree:def __init__(self, basewidth=100, basedepth=100):

self.basewidth=basewidth

self.basedepth=basedepth

self.root=Nonedefgentree(self, db, mothervalue, tablename, childcol, mothercol):

self.root=decisionnode(mothervalue)

cur=db.cursor()defswap_gentree(node):

cur.execute("select %s from %s where %s = '%s'" %\

(childcol, tablename, mothercol, node.value));

results=cur.fetchall()#如果是叶子节点,则直接返回

if notresults:return decisionnode(node.value, isleaf=True, maxlevel=1)#程序运行到这里,说明是非叶子节点

#对非叶子节点进行其下包含的叶子节点进行统计(leafcounts)

#该节点之下最深的深度maxlevel收集

maxlevel=1

for each inresults:

entrynode=swap_gentree(decisionnode(each[0]))if(entrynode.isleaf):

node.leafcounts+= 1

else:

node.leafcounts+=entrynode.leafcountsif (entrynode.maxlevel >maxlevel):

maxlevel=entrynode.maxlevel

node.addchild(entrynode)

node.maxlevel= maxlevel+1

returnnode

swap_gentree(self.root)defdraweachnode(self, tree, draw, x, y):

draw.text((x,y), tree.value, (0,0,0))if nottree.childs:returnchilds_leafcounts=[child.leafcounts if child.leafcounts else 1 for child intree.childs]

leafpoint=x-sum(childs_leafcounts)*self.basewidth/2cumpoint=0for childtree, point inzip(tree.childs, childs_leafcounts):

centerpoint=leafpoint+self.basewidth*cumpoint+self.basewidth*point/2cumpoint+=point

draw.line((x,y, centerpoint, y+self.basedepth), (255,0,0))

self.draweachnode(childtree, draw, centerpoint, y+self.basedepth)def drawTree(self, filename='tree.jpg'):

width=self.root.leafcounts * self.basewidth +self.basewidth

depth=self.root.maxlevel * self.basedepth +self.basedepth

img=Image.new(mode="RGB", size=(width, depth), color=(255,255,255))

draw=ImageDraw.Draw(img)

self.draweachnode(self.root, draw, width/2, 20)

img.save(filename)

测试验收

确认运行代码的环境是否已经安装以下包

pillow (如果没有请pip install pillow (这个模块实际上就是PIL))

sqlite3 (如果没有请pip install sqlite3)

新建一个文件 drawtree.py

在文件开头导入需要的模块

import sqlite3

from PIL import Image, ImageDraw

然后将上面的代码复制进去

然后根据下面操作

1151103-20170611182449450-2095744253.png

到这里,就会在工作目录下生成tree.jpg了,效果就像文章开头那样,

为了程序的通用性,本例的程序已经写成很通用的代码了,如果你用的是其他数据库

则不要用我的样本数据,也就是不要运行drawtree.sampledata这个函数

然后将db=sqlite3.connect('daname,db')换成你数据库对应的连接,例如你的数据库是oracle,则用db=cx_Oracle.connect('usernae/password@tnsname')

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值