Bottle UiKit Python实现的前后端交互代码实现

编程入门 行业动态 更新时间:2024-10-08 20:33:56

Bottle UiKit Python实现的前<a href=https://www.elefans.com/category/jswz/34/1771414.html style=后端交互代码实现"/>

Bottle UiKit Python实现的前后端交互代码实现

文章目录

  • 项目所在 GitHub 地址
  • 1、项目整体思路
  • 2、项目实现技术
  • 3、前端界面实现
  • 4、后端服务器框架 bottle 简单介绍
  • 5、python 代码实现
    • 5.1 main.py
    • 5.2 Callibration.py
  • 6、前后端交互的重点以及难点
    • 6.1、实现前后端交互之上传文件
    • 6.2、实现前后端交互之实现参数的传递
    • 6.3、实现前后端交互之前端点击按钮后端实现相应的操作
    • 6.4、实现前后端交互之实现静态文件的传递
    • 6.5、点击按钮实现图片的展示
  • 7 其他项目中用到的小程序
    • 7.1、使用python 进行文件的压缩以及文件拷贝到指定文件夹

项目所在 GitHub 地址

.git

1、项目整体思路

在前端的网页中进行文件的上传,在后端对于前端上传的文件进行数据处理,返回处理结果。在这个开发小项目中,返回的处理结果是数据处理产生的中间文件以及后端数据经过处理得到的图片文件;

说明:

中间文件文本文件
图片文件png 文件

简单来讲,整个项目就是输入–>处理–> 输出的简单逻辑。

2、项目实现技术

整体技术具体使用
前端语言html css javascript
前端UI框架uikit
后端服务器框架bottle
后端编程语言Python

3、前端界面实现

4、后端服务器框架 bottle 简单介绍

轻量级服务器框架,国内的查询资料较少,谨慎使用

5、python 代码实现

5.1 main.py

import Calibration
# 读取文件
High = []
Mid = []
Low = []# 前端读取到的文件可以保存在一个文件夹下面就好了,这样下面的代码就不用修改了path = 'Spectral_Data/'
for i in range(1, 8):filename_high = path + 'Spectrum_' + str(i) + "_0_1.sps"filename_mid = path + 'Spectrum_' + str(i) + "_1.sps"filename_low = path + 'Spectrum_' + str(i) + "_1_1.sps"High.append(Calibration.import_file(filename_high))Mid.append(Calibration.import_file(filename_mid))Low.append(Calibration.import_file(filename_low))
diff_high = Calibration.cal_dif(High, 7)
diff_mid = Calibration.cal_dif(Mid, 7)
diff_low = Calibration.cal_dif(Low, 7)# 开始拟合
# 计算多项式系数
my_M = 2
my_N = 3
my_lamda = 0
Polynomial_Coefficients = []  # 拟合的多项式系数
result = []  # 中等光强下,定标后的结果# 计算结果的导出文件夹路径的设置
savepath = "out/"
for row in range(0, 6):temp_args = []temp_result = []temp_args1 = []temp_result1 = []args_dis = []result_dis = []for col in range(0, len(diff_low[0])):my_x_n = [diff_low[row][col], diff_mid[row][col], diff_high[row][col]]my_y_n = [Low[row + 1][col], Mid[row + 1][col], High[row + 1][col]]# 方法1:Numpy自带的多项式拟合函数temp_args.append(Calibration.np.polyfit(my_y_n, my_x_n, 2))func = Calibration.np.poly1d(temp_args[col])temp_result.append(Mid[row+1][col] - func(Mid[row+1][col]))# print("numpy自带的Polyfit:", temp_args[col])# print("numpy自带的Polyld :", temp_result[col])# 方法2:自己写的多项式拟合函数temp_args1.append(Calibration.ployfit(my_M, my_N, my_y_n, my_x_n, my_lamda))temp_result1.append(Mid[row+1][col] - Calibration.ployval(temp_args[col], Mid[row + 1][col]))# print("自己写的:", temp_args1[col])# print("自己写的:", temp_result1[col])dis_args = [temp_args[col][0]-temp_args1[col][2], temp_args[col][1]-temp_args1[col][1], temp_args[col][2]-temp_args1[col][0]]args_dis.append(dis_args)result_dis.append(temp_result[col] - temp_result1[col])Polynomial_Coefficients.append(temp_args)   # 保存的多项式参数:a*x^2 + b*x + c中的a,b,cresult.append(temp_result)                  # 保存的定标结果Calibration.export_file(Polynomial_Coefficients[row], savepath, "Light_" + str(row + 1) + ".conf")
print("计算结束!")Calibration.draw_pic(High, "1-High Light Intensity", 1)
Calibration.draw_pic(Mid, "1-Middle Light Intensity", 2)
Calibration.draw_pic(Low, "1-Low Light Intensity", 3)
Calibration.draw_pic(diff_low, "2-Low Light Difference", 4)
Calibration.draw_pic(diff_mid, "2-Middle Light Difference", 5)
Calibration.draw_pic(diff_high, "2-High Light Difference", 6)
Calibration.draw_pic(result, "Middle Light Calibration Difference(Numpy - Myself)", 7)# 图片可以保存在其他的路径中
# 后期进行代码的重构,使得保存图片可以保存在给定的问价夹路径中

5.2 Callibration.py

# 读取数据文件,计算定标参数,保存定标参数
# Yangkai,2021/11/19
import numpy as np
import matplotlib.pyplot as plt
import numpy.linalgdef cal_dif(matrix_data, light_number):"""计算传入的二位列表,以第1列为标准,计算其它列到第1列的差值:param matrix_data: 浮点数,二位列表,每一列代表一根光纤的测量值:param light_number: 整数,光纤个数:return: 返回光纤个数-1的二维列表,其它光纤同波段下距第1根光纤的差值"""difference = []try:for row1 in range(1, light_number):dis = []for col1 in range(0, len(matrix_data[0])):temp_dis = matrix_data[row1][col1] - matrix_data[0][col1]dis.append(temp_dis)# print("temp_dis:", temp_dis)difference.append(dis)# print(dis)# print(difference)except IndexError:print("Error: 索引超出列表范围!请检查传入列表的维度")finally:return differencedef import_file(filename):"""读取sps光谱数据,忽略波段,只读取DN值:param filename: 文件名:return: 返回该文件DN值的一维列表"""fo = open(filename, "r+")data = []try:print("当前正在读取:", fo.name)for row1 in fo.readlines()[26:]:  # 从26行开始读取,跳过文件头line = row1.strip()  # strip函数删掉每一行数字前面的空格data.append(float(line[13:]))  # 一个文件的数据放进一个列表except IOError:print("Error: 没有找到文件或读取失败")except IndexError:print("Error: 索引超出列表范围,请检查文件内容!")else:print("文件读取成功!")finally:fo.close()return datadef ployfit(m, n, x, y, lamda):"""对输入的参数进行M次多项式的拟合,返回拟合的多项式系数:param m: 拟合的多项式阶数:param n: 输入拟合数据的个数:param x: 待拟合的x,即各光照强度:param y: 待拟合的y,即各光照强度下的差值Δ:param lamda: 正则项系数,默认为0,即无正则项:return: 多项式系数的列表"""# print("\n输入参数为:M=%d, N=%d, x_n=(%.4f,%.4f,%.4f), t_n=(%.4f,%.4f,%.4f)" % (# M, N, x_n[0], x_n[1], x_n[2], t_n[0], t_n[1], t_n[2]))order = np.arange(m + 1)        # 生成一个从0-m的列表order = order[:, np.newaxis]    # 提取所有行,升维,变成m*1的二维矩阵e = np.tile(order, [1, n])      # 在行方向上复制1次,列方向上复制n次x_t = np.power(x, e)            # 对传进来的x,求矩阵X = np.transpose(x_t)a = np.matmul(x_t, X) + lamda * np.identity(m + 1)  # X.T * Xb = np.matmul(x_t, y)   # X.T * T# numpy.linalg中的函数solve可以求解形如 Ax = b 的线性方程组w = numpy.linalg.solve(a, b)# w = np.matmul(np.linalg.inv(a), b)  # aW = b => (X.T * X) * W = X.T * Treturn wdef ployval(args, x):"""根据多项式系数,计算x处的y值:param args: 多项式系数,一维列表:param x: 待求点的x:return:  待求点的y"""y = 0.0try:if len(args) == 0:print("输入的阶数为0!无法拟合!")else:# y1 = args[0] + args[1]*x + args[2]*x*xfor rank in range(0, len(args)):y += args[rank] * (x ** (len(args)-rank-1))     # y = (w_0 * x^2) + (w_1 * x^1) + (w_2 * x^0)except IndexError:print("Error: 索引超出列表范围!")finally:return y# 画图
def draw_pic(matrix_data, title, pic_num):"""画图函数:param matrix_data: 传入的二维矩阵:param title: 图标题和保存的文件名,用同一个字符串:param pic_num: 是第几副图"""font = {'family': 'Times New Roman', 'size': 30, 'weight': 'bold'}n = list(range(350, 1021))plt.figure(num=pic_num, figsize=(15, 10))for i in range(0, len(matrix_data)):plt.plot(n, matrix_data[i], linewidth=3, label='NO.'+str(i+2))plt.tick_params(labelsize=15)plt.xticks(np.linspace(350, 1020, 10))plt.xlim(340, 1030)plt.grid(linestyle=":", color="k")plt.xlabel('Wavelength(nm)', font)plt.ylabel('Intensity(DN)', font)plt.title(title, font)plt.legend(loc='upper right', frameon=True, fontsize=25)plt.savefig("./" + title + ".png", dpi=600)plt.show()print("绘制成功!图片已保存")# 输出到文件
def export_file(matrix_data, filepath, filename):"""输出到文件:param matrix_data: 要保存的数据:param filepath:    文件保存路径:param filename:    希望保存的文件名"""try:with open(filepath+filename, 'w+') as fid:for row in range(0, len(matrix_data)):fid.write("%20.15f %20.15f %20.15f\n" % (matrix_data[row][0], matrix_data[row][1], matrix_data[row][2]))except IOError:print("ERROR: 输出失败!请检查路径、文件名以及数据!")else:print("文件保存成功!")finally:print("输出函数调用结束")

6、前后端交互的重点以及难点

6.1、实现前后端交互之上传文件

前端代码:

            <p class="uk-heading-line uk-text-center J-block-title"><span>文件上传</span></p><div class="js-upload uk-placeholder uk-text-center"><span uk-icon="icon: cloud-upload"></span><span class="uk-text-middle">拖动文件 or</span><div uk-form-custom><input type="file" multiple='multiple'><span class="uk-link">点击选择标准光谱文件</span></div><progress id="js-progressbar" class="uk-progress" value="0" max="100" hidden></progress></div><div class="js-upload uk-placeholder uk-text-center"><span uk-icon="icon: cloud-upload"></span><span class="uk-text-middle">拖动文件 or</span><div uk-form-custom><input type="file" multiple='multiple'><span class="uk-link">点击选择观测光谱文件</span></div><progress id="js-progressbar1" class="uk-progress" value="0" max="100" hidden></progress></div>
        <script>var bar = document.getElementById('js-progressbar');UIkit.upload('.js-upload', {url: '/1',multiple: true,name: 'Spectral_Data',beforeSend: function () {console.log('beforeSend', arguments);},beforeAll: function () {console.log('beforeAll', arguments);},load: function () {console.log('load', arguments);},error: function () {console.log('error', arguments);},complete: function () {console.log('complete', arguments);},loadStart: function (e) {console.log('loadStart', arguments);bar.removeAttribute('hidden');bar.max = e.total;bar.value = e.loaded;},progress: function (e) {console.log('progress', arguments);bar.max = e.total;bar.value = e.loaded;},loadEnd: function (e) {console.log('loadEnd', arguments);bar.max = e.total;bar.value = e.loaded;},completeAll: function () {console.log('completeAll', arguments);setTimeout(function () {bar.setAttribute('hidden', 'hidden');}, 1000);alert('Upload Completed');}});</script>

后端代码:

# 这个是和前端的上传文件控件进行的绑定,可以设置文件保存的路径
@route('/1', method='POST')
def backData():upload = request.files.get('Spectral_Data')upload.save(r'./Spectral_Data')return 'ok'

注意有一个 url 需要配置,这个必须和后端进行绑定
在后端服务器中 get(‘Spectral_Data’) 得到到前端的
name :Spectral_Data,这样子前后端就能实现通讯了,也就是可以进行上传文件了;

6.2、实现前后端交互之实现参数的传递

前端代码:

            <div class="form-group" uk-margin style="text-align: center;"><form class="uk-form-horizontal" action="/obsconfig" method="post"><div class="uk-margin"><label class="uk-form-label" for="form_ftp1">定标轮次</label><div class="uk-inline J-modity-input"><span class="uk-form-icon uk-form-icon-flip"></span><input class="uk-input" type="text" id="DingBiaoLunCi" name="DingBiao"></div></div><div class="uk-margin"><label class="uk-form-label" for="form_ftp2">光纤数目</label><div class="uk-inline J-modity-input"><span class="uk-form-icon uk-form-icon-flip"></span><input class="uk-input" type="text" id="form_ftp_usrname" name="GuangQian"></div></div><p uk-margin style="margin: 45px 0 30px;"><button class="uk-button uk-button-primary uk-width-1-1 uk-margin-small-bottom" type="submit">参数输入完毕点击确定</button></p></form></div>

后端代码:

# 进行配置参数的获取
@route('/obsconfig', method='POST')
def tem():# 使用数组或者某种存储容器存储表格中传递过来的相关参数# form = 'html' 里面的 name 进行获取forms = {}forms['DingBiao'] = request.forms.get('DingBiao')forms['GuangQian'] = request.forms.get('GuangQian')print(forms)return template('templates/光谱仪定标.html')

需要注意:
下图中在前后端中这两个位置的参数必须是一致的,这样子后端才能接受到前端传递的参数,相当于快递员快递,总得知道自己从什么地方出发,到什么地方去,计算机就是机械的进行执行命令;

6.3、实现前后端交互之前端点击按钮后端实现相应的操作

前端代码:

            <p class="uk-heading-line uk-text-center J-block-title"><span>相关操作</span></p><!-- 创建需要的按钮即可 --><div class="js-upload uk-placeholder uk-text-center"><p uk-margin style="text-align: center;"><button class="uk-button uk-button-default" id='getCalibration'>光谱仪定标</button><div class="uk-inline" style="display:inline-block"><button class="uk-button uk-button-default" type="button">导出</button><div uk-dropdown><p><a href="http://localhost:8088/result/out.zip" download="result">导出定标参数</a></p></div></div></p></div>
        <script>var btnFLD = document.getElementById("getCalibration");btnFLD.onclick = function () {var httpRequest = new XMLHttpRequest();//第一步:创建需要的对象httpRequest.open('POST', 'http://localhost:8088/getCalibration', true); //第二步:打开连接httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");//设置请求头 注:post方式必须设置请求头(在建立连接后设置请求头)httpRequest.send();//发送请求 将情头体写在send中}const commodity_image = document.createElement("img");let imageURL = "/images?skuid=" + r[j]["skuid"];commodity_image.src = imageURL;</script>

后端代码:

# 这个是和前端的按钮进行的绑定,点击按钮调用后端的 main.py 的脚本文件,进行图片的生成
@route('/getCalibration', method='POST')
def getCalibration():os.system("python main.py")

需要注意:
前后端的这两个参数需要相同,实现前后端的绑定,实现动态交互

6.4、实现前后端交互之实现静态文件的传递

前后端进行的图片展示传递的思路:
在服务器端会产生一系列的图片文件,每个文件会有自己的url;
在 标签中 的 src 属性中填写 图片的 url 即可;

6.5、点击按钮实现图片的展示

前端代码:

            <p class="uk-heading-line uk-text-center J-block-title"><span>结果</span></p><div class="js-upload uk-placeholder uk-text-center"><!-- 在这里传上去后端处理好的图片 --><img id="myImage" src=".jpg"/><button onclick="handle()" class="uk-button uk-button-default" type="button">显示图片1</button><img id="myImage" src=""/><button onclick="handle1()" class="uk-button uk-button-default" type="button">显示图片2</button><img id="myImage" src=""/><button onclick="handle2()" class="uk-button uk-button-default" type="button">显示图片3</button><img id="myImage" src=""/><button onclick="handle3()" class="uk-button uk-button-default" type="button">显示图片4</button><img id="myImage" src=""/><button onclick="handle4()" class="uk-button uk-button-default" type="button">显示图片5</button><img id="myImage" src=""/><button onclick="handle5()" class="uk-button uk-button-default" type="button">显示图片6</button><img id="myImage" src=""/><button onclick="handle6()" class="uk-button uk-button-default" type="button">显示图片7</button></div>
        <script>function handle() {document.getElementById('myImage').src = '.jpg';}function handle1() {document.getElementById('myImage').src = '.jpg';}function handle2() {document.getElementById('myImage').src = '.jpg';}function handle3() {document.getElementById('myImage').src = '.jpg';}function handle4() {document.getElementById('myImage').src = '.jpg';}function handle5() {document.getElementById('myImage').src = '.jpg';}function handle6() {document.getElementById('myImage').src = '.jpg';}</script>

注意:实现点击按钮进行图片的更换,处理函数的名字必须是一致的,这样子,才能把 html 与 javascript 进行绑定,实现相关的功能;

7 其他项目中用到的小程序

7.1、使用python 进行文件的压缩以及文件拷贝到指定文件夹

import zipfile
import os
import shutil
# 将参数计算成功之后,将计算的结果使用压缩包的形式进行发送到前端startdir = "./out"  #要压缩的文件夹路径
file_news = startdir +'.zip' # 压缩后文件夹的名字
z = zipfile.ZipFile(file_news,'w',zipfile.ZIP_DEFLATED) #参数一:文件夹名
for dirpath, dirnames, filenames in os.walk(startdir):fpath = dirpath.replace(startdir,'') #这一句很重要,不replace的话,就从根目录开始复制fpath = fpath and fpath + os.sep or ''#这句话理解我也点郁闷,实现当前文件夹以及包含的所有文件的压缩for filename in filenames:z.write(os.path.join(dirpath, filename),fpath+filename)print ('压缩成功')
z.close()# 移动文件夹示例
# 将参数的文件移动到 result 文件夹中使用前端的按钮可以进行文件的下载
# 进行文件移动的代码的重写,向前端返回一个计算结束后面的压缩包
if not os.path.exists("./static/result/out.zip"):shutil.move("./out.zip", "./static/result/")

更多推荐

Bottle UiKit Python实现的前后端交互代码实现

本文发布于:2024-02-26 18:58:36,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1703535.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:后端   代码   Bottle   UiKit   Python

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!