调用服务器上的脚本
使用脚本计算平均CPI,并更新到数据库中。主要涉及到在python脚本里处理数据,并写入数据库
- 之前曾用过后端脚本实现过计算
平均GDP
,直接调用DWF的api - python脚本没有DWF的api,如果希望和DWF的数据库交互,需要手动解决认证问题,数据库api问题,因此用自己的脚本文件与DWF的数据库交互是不推荐的,需要额外增加相当多的工作量。
在进入下面的工作前,让我们先在Data实体类里创建一列平均CPI
,用于之后的计算使用
认证
认证使用登陆DWF的用户名及密码即可,认证方式分为以下两个步骤
使用用户名密码从服务器获取token
使用token向DWF服务端发起数据库请求
上面两个步骤在后端脚本或者前端脚本已经封装好了,所以只要我们是在DWF里写脚本,就不需要处理这种事情。
但是如果是自己的脚本,就必须要把上面的流程走一遍。
如果你不需要和后端数据库交互,那么这部分的认证流程完全可以跳过,直接进入
调用你的python脚本
部分即可
认证的api在API说明里有,例子如下
import os, argparse, requests, json
host='http://101.6.15.212:9503'#改成你的host:port,注意这个port不是modeler-web那个port,你要从api说明里面找
jwt='eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTU5NzQ3MTIxMn0.eXjRtWJleuWvs_MlZTT7YYf8rv2JtqP8DbXKbhl5Z1fyFsRoFU4gKwDeUD600gI8wGKfClwfkzqWs-4rnTdOzg'#改成你的jwt,在api说明里获取
header={"Authorization": jwt, "Content-Type": "application/json"}# Get请求的header
r = requests.get(host+'/dwf/v1/app/login?userName={}&password={}'.format('admin','123456'), #替换成你的用户名以及密码,注意我填的密码不是真正的密码,所以直接执行该行代码会失败
headers=header)
# update jwt
jwt = r.json()['data']
header={"Authorization": jwt, "Content-Type": "application/json"}# Get请求的header
# 测试你的jwt能否成功认证,我们发送一个post请求获取Data数据,根据你的类名,可能你的实体类名字不是Data
r= requests.post(host+'/dwf/v1/omf/entities/Data/objects',headers=header,
json={
"condition" : "and obj.year>={} and obj.year<{}".format(2012, 2019)
})
print(r.json()['data'])
# 此处会输出内容
在上面的代码里中需要year
是数字类型,否则查询数据库进行比较时会报错,大家可以把condition那一行的查询改为SQL的原生查询
"condition" : "nativequery:select plt_CPI as \"CPI\",plt_oid as \"oid\",plt_totalPopulation as \"totalPopulation\" FROM plt_CUS_Data where cast(plt_year as integer)>2012 and cast(plt_year as integer)<2019"
其中cast
将数据转换为integer后比较
另外如果你需要使用其它的python的库,请务必提前在服务器上安装好,比如大家现在用的docker,你需要进入docker后安装相应的包,也可以尝试用后端脚本,但是无法知道是否安装成功
this.sh.execute("pip install jupyter")
另外DWF开发课题组提供了DWFIO.py
文件,将上述的认证过程封装在类里,可以作为模块导入,详细内容和文件下载在这里
数据库请求
数据库请求的api在API说明里有,例子如下
df = r.json()['data']
tmpts = []
for i,t in enumerate(df):
tmpt = {
'oid': t['oid'],
'avgCPI': t['CPI']/t['totalPopulation']
}
tmpts.append(tmpt)
# 上面将需要更新的内容按照oid储存成数组,下面可以直接放在api里更新
r = requests.post(host+'/dwf/v1/omf/entities/Data/objects-update',
headers=header,
json=tmpts)
上面计算avgCPI
的过程中由于部分同学表格里类型是字符串,所以需要加上float()进行类型转换,其实这一步可以在sql查询时使用cast转换;另外由于一些同学数据里可能有空行,所以需要加上判断
df = r.json()['data']
tmpts = []
for i,t in enumerate(df):
if 'CPI' in t.keys():
tmpt = {
'oid': t['oid'],
'avgCPI': float(t['CPI'])/float(t['totalPopulation'])
}
tmpts.append(tmpt)
# 上面将需要更新的内容按照oid储存成数组,下面可以直接放在api里更新
r = requests.post(host+'/dwf/v1/omf/entities/Data/objects-update',
headers=header,
json=tmpts)
之后你可以检查你的数据库看是否更新
- 如果我们本地测试没有问题了,那么可以将这个脚本上传到dwf上,可以利用之前在part2里创建的
脚本文件
的实体类表单,上传附件功能。- 上传完脚本文件后,记录对应的
oid
,之后获取文件路径需要
- 上传完脚本文件后,记录对应的
- 如果你有权限直接接触到后端服务器,那么可以直接将脚本文件创建在某个文件夹下,路径由自己管理
调用你的python脚本
在part2部分,我曾经讲过调用python脚本,此处引用那里的内容
- 在做这个操作前,确保你的脚本能够在本地运行,这个事情很重要,因为DWF里看不到脚本文件执行的输出结果,你是无法知道它的出错位置
- 获得脚本文件路径: 此处已经有简单的方式,参考附录部分,可以直接在
code-server
界面将你的脚本文件上传 - 执行脚本 此处我们需要创建一个按钮,并添加操作后端脚本
//获取文件路径,下面的实体类Script按照你上传的实体类名称为准
oid='49419988FD6E044799061CE396AE3DED'
var scriptPath = this.omf.getFilePath(oid, 'Script', 'scriptFile');
//执行脚本,反引号将变量替换成值
this.sh.execute(`python3 ${scriptPath}`)
上面的方式需要创建一个文件的实体类,如果直接上传了脚本文件,可以用下面的方式
- 前端脚本
// this.serverDebugger();
this.callServer().then(res => {
console.log(res.data.data);
this.msgbox.info(res.data.data);
})
- 后端脚本
var scriptPath = "/home/dwfcoder/src/L1-HelloWorld.py";
var r = this.sh.execute(`python3 ${scriptPath}`);
this.res = r;
其中使用print
打印字符时需要dump
注意事项
务必不要将带有密码的脚本文件以public推到github或者其它方式公开,会暴露你的dwf登录密码,有安全隐患