本次测试操作采用db.sqlite3保存结点和关系信息,后期可以通过在settings中配置数据库使用其他数据库。
1、 创建Node类型的model
a) Name:结点名字
b) belong_to:结点归类
c) desc:结点描述
d) category:结点在前端展示的结点类型
其中name属性表示结点的唯一属性,当然也可以添加id等唯一标识符,这里name只是为了在添加结点时候更加直观显示。
belong_to和 desc是结点的属性,可自行添加其他属性。
category是为了在前端显示时候,通过不同的显示区别不同结点。
2、创建Edge类型的model
a) source:结点源点
b) target:结点终点
c) value:关系描述
这里也可以通过指定id来唯一标志关系边,这边是通过source和target来一起确定关系边的。
其中source和target表示关系的开始和结束结点,这里使用结点的名字。
value表示关系边的一个属性,就是一个标签,当然也可以添加其他属性。
Note: 这里结点和关系边可以设置一个is_show来设置结点是否被删除,因为在真正的开发中,数据不会被真正的删除。
前端展示知识图谱主要通过百度开源Echarts库实现,快速入门教程可参考:https://echarts.apache.org/zh/tutorial.html#5%20%E5%88%86%E9%92%9F%E4%B8%8A%E6%89%8B%20ECharts
var myChart = echarts.init(document.getElementById('graph'));
myChart.setOption(option);
关于option设置,可参考Echarts中关于option参数的设置
下面主要讲解series的设置,其中参数可参考Echarts中关系图的series选项参数
series: [
{
type: 'graph', {# 表示这是画一个关系图 #}
layout: 'force',{# 表示这是力导向的关系图 #}
symbolSize: 45,
focusNodeAdjacency: true,{# 表示鼠标移上结点或者箭头其相关元素是否高亮 #}
draggable:true,{# 表示结点可以拖动 #}
roam: true,{# 表示图形可以放大缩小 #}
edgeSymbol: ['none', 'arrow'],
categories: [{{# 用来保存不同分类结点的样式 #}
name: '查询实体',
itemStyle: {
normal: {
color: "#009800",
}
}
}, {
name: 'instance',
itemStyle: {
normal: {
color: "#4592FF",
}
}
}, {
name: 'class',
itemStyle: {
normal: {
color: "#C71585",
}
}
}],
label: {
normal: {
show: true,
textStyle: {
fontSize: 12,
},
}
},
force: {
repulsion: 1000
},
edgeSymbolSize: [4, 50],
edgeLabel: {
normal: {
show: true,{# 表示箭头会显示关系 #}
textStyle: {
fontSize: 10
},
formatter: "{c}"
}
},
data: data,{# 传入结点信息 #}
links: links,{# 传入关系箭头信息 #}
lineStyle: {
normal: {
opacity: 0.9,
width: 1.3,
curveness: 0,
color:"#262626",
}
}
}
]
在前端页面的知识图谱展示过程中,前端知识图谱只需要后端传入data和links数据就可以做到知识图谱的展示,所以,在后面的知识图谱中的增删改查操作中,可以通过前端发送操作请求,然后实现数据库的增删改查,然后刷新页面的方式从而实现知识图谱中结点的操作。
通过输入127.0.0.1:8080/graph地址(这里的地址在后期部署时候需要替换),向后端发送请求,
后端通过knowledge中的urls和graph中的urls来进行路由调用graph中的views中的graph函数对请求进行处理。
Knowledge中的urls
urlpatterns = [
path('graph/', include('graph.urls')),
path('admin/', admin.site.urls),
]
Graph中的urls
urlpatterns = [
path('delete/', views.delete, name='delete'),
path('add/', views.add, name='delete'),
path('update/', views.update, name='delete'),
path('', views.graph, name='index'),
]
Graph中views中的graph函数,用来处理显示数据的函数,通过graph/graph.html显示,并将数据通过json封装起来传到前端:
def graph(request):
# data, links = create_data()
data, links = get_data_links()
d1 = json.dumps(data)
l1 = json.dumps(links)
return render(request, 'graph/graph.html', {'data': d1, 'links': l1})
其中get_data_links()函数是将数据库中的数据拿出来封装成前端页面显示需要的data和links数据,这里数据库中的数据和封装成前端页面显示需要的数据需要根据实际情况改变,如下代码所示:
def get_data_links():
data = Node.objects.all()
node = []
for d in data:
da = {'value': {'belong_to': '', 'desc': '', }, 'category': 0}
da['name'] = d.name
da['value']['belong_to'] = d.belong_to
da['value']['desc'] = d.desc
da['category'] = int(d.category)
node.append(da)
links = Edge.objects.all()
edge = []
for l in links:
li = {'source': '', 'target': '', 'category': 0, 'value': '', 'symbolSize': 10}
li['source'] = l.source
li['target'] = l.target
li['value'] = l.value
edge.append(li)
return node, edge
在点击结点或边时候,主要通过echarts库自带的事件函数中的params参数获取结点数据,并通过结点绑定显示到页面中。
myChart.on('click', function (params) {
if (params.dataType === 'edge') {
// 点击到graph的edge上
var edge_name = document.getElementById('edge')//获取需要显示在哪里的盒子
var source = document.getElementById('source')
var target = document.getElementById('target')
edge_name.innerHTML = params.data.value //将params中的信息放到需要显示的盒子中
source.innerHTML = params.data.source
target.innerHTML = params.data.target
}
else {
// 点击到graph的node上
var node_name = document.getElementById('node')
var belong_to = document.getElementById('belong_to')
var desc = document.getElementById('desc')
node_name.innerHTML = params.data.name
belong_to.innerHTML = params.data.value.belong_to
desc.innerHTML = params.data.value.desc
}
})
这里结点信息展示过程中,由于结点信息都放在前端,所以不用去后端拿数据,如果前端没有数据,可以根据结点名字通过AJAX技术去后端请求结点代表的所有信息,然后展示在页面上。
这里通过展示一个通过改变数据库信息,然后自动刷新页面从而达到删除数据的效果。
首先,我们建立一个id=delete的button按钮,点击一个结点或边,我们可以显示结点或边的信息。
我们给id=delete的button绑定一个函数,通过jQuery中的AJAX技术,将结点名字(唯一标识符)传到后端。
node = document.getElementById("node");
$("#delete").click(function(){
$.ajax({
url: '/graph/delete/', //请求地址
type: "GET", //请求类型
data: { //发送数据 键值对形式
node_name: node.innerText,
},
success: function (data) {
alert('删除成功') //回调函数
window.location.reload();
}
})
});
其中,node表示点击一个结点或边获取的唯一标记,后期开发中可以使用id作为结点和边的数据库中信息的唯一标识符,url表示‘127.0.0.1:8080‘ + ‘graph/delete/’ 这里url分为绝对地址和相对地址。
然后,后端通过knowledge中的urls和graph中的urls地址路由到graph中的views中的delete函数,实现对数据库的删除,然后重载数据请求页面,达到删除的效果。
urlpatterns = [
path('delete/', views.delete, name='delete'),
path('add/', views.add, name='delete'),
path('update/', views.update, name='delete'),
path('', views.graph, name='index'),
]
在页面中开一个表单,用来填写结点信息,然后发送给后端/add函数函数通过将前端传过来的数据添加进相应的数据库中,然后自动刷新页面
点击一个结点,结点的信息会显示在页面上,点击修改,结点信息会以表单的形式显示在页面上,通过修改表单的数据,然后提交到后台的\update()函数,函数通过将前端传过来的数据更新数据库,然后自动刷新页面,实现修改结点的效果。
本博文供学习交流所用,参考了大量的博文和书本。
[1] Echarts参考手册 https://echarts.apache.org/zh/option.html#title
[2] Djangou菜鸟教程 https://www.runoob.com/django/django-tutorial.html
[3] 游离态GLZ不可能是金融技术宅. 如何在网页前端里可视化你的知识图谱. https://blog.csdn.net/qq_37477357/article/details/104857495