当前位置:   article > 正文

基于Flask的简单Web应用_基于flask的web应用系统

基于flask的web应用系统

一、前言

前段时间,老师让设计一个用于插值的GUI界面,便想着用刚学不久的Web框架Flask做一个。

为什么呢?Flask是一个用于Python的轻量级Web框架,简单易用,最适合我这种初学者了。

二、准备工作

开整之前,最好为电脑上的python安装以下库:

pip install scipy flask numpy

三、前端实现

设计一个GUI界面,那肯定得有界面咯,用html先敲一个框架。要有标题、按钮、显示插值图像的图表。。。。。。

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
  5. </head>
  6. <body>
  7. <div id="header">
  8. <title>三次样条函数插值</title>
  9. </div>
  10. <div id="content">
  11. <label for="dataFile">上传数据文件:</label>
  12. <input type="file" id="dataFile" accept=".csv">
  13. <label for="boundary-condition">选择边界条件:</label>
  14. <select id="boundary-condition">
  15. <option value="I型">I型</option>
  16. <option value="II型">II型</option>
  17. </select>
  18. <input type="number" , name="left-boundary-condition" ,
  19. id="leftBoundaryCondition" , placeholder=0 , value=0>
  20. <input type="number" , name="right-boundary-condition" ,
  21. id="rightBoundaryCondition" , placeholder=0 , value=0>
  22. <button onclick="sendInputToPython()">上传并插值</button>
  23. <div id="chart-container">
  24. <label for="chart">图像:</label>
  25. <div id="chart"></div>
  26. </div>
  27. <label for="interpDataFile">上传需要插值的数据文件:</label>
  28. <input type="file" id="interpDataFile" accept=".csv">
  29. <button onclick="saveInterpDataFile()">插值并下载</button>
  30. <div class="btn-container">
  31. <button onclick="clearChart()">清空图像</button>
  32. </div>
  33. </div>
  34. </body>
  35. </html>

运行一下吧。

嗯?虽说该有的都有了,但是感觉不太好看。用css修饰一下,加点颜色、改改位置,改改大小。。。。。。

  1. <style>
  2. body {
  3. font-family: Arial, sans-serif;
  4. background-color: #f5f5f5;
  5. /* background-image: url(../static/2053223.jpg); */
  6. background-size: cover;
  7. background-repeat: no-repeat;
  8. background-attachment: fixed;
  9. margin: 0;
  10. padding: 0;
  11. }
  12. #header {
  13. background-color: #3498db;
  14. color: #fff;
  15. text-align: center;
  16. padding: 20px 0;
  17. }
  18. #content {
  19. max-width: 800px;
  20. margin: 0 auto;
  21. background-color: #fff;
  22. padding: 20px;
  23. border-radius: 5px;
  24. box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  25. }
  26. h1 {
  27. font-size: 24px;
  28. }
  29. label {
  30. font-weight: bold;
  31. }
  32. input[type="number"] {
  33. width: 50px;
  34. }
  35. .btn-container {
  36. margin-top: 20px;
  37. }
  38. button {
  39. padding: 10px 20px;
  40. background-color: #3498db;
  41. color: #fff;
  42. border: none;
  43. border-radius: 5px;
  44. cursor: pointer;
  45. margin-right: 10px;
  46. }
  47. #chart {
  48. width: 100%;
  49. height: 400px;
  50. }
  51. </style>

加上css修饰之后,再运行一下。

这就舒服多了。

当然,现在点击那些按钮并不会有任何反应,因为响应函数还没写呢。

四、按钮响应函数实现

先来看第一个按钮,<选择文件>。不同文件有不同的解析方式,这里就仅考虑csv格式的数据文件。因为做的是插值,希望第一行代表自变量,第二行代表因变量,当然有的插值需要用到导数,所以如果有第三行就读取为导数。整体逻辑有了,我们用js来实现一下。

  1. function parseCSVData(csvContent) {
  2. var lines = csvContent.split('\n');
  3. var xValues = lines[0] ? lines[0].split(',') : [];
  4. var yValues = lines[1] ? lines[1].split(',') : [];
  5. var derivativeValues = lines[2] ? lines[2].split(',') : [];
  6. var data = {
  7. x: xValues.map(parseFloat),
  8. y: yValues.map(parseFloat),
  9. derivative: derivativeValues.map(parseFloat)
  10. };
  11. return data;
  12. }
  13. var fileInput = document.getElementById("dataFile");
  14. var file = fileInput.files[0];
  15. if (!file) {
  16. alert("请先选择一个数据文件。");
  17. return;
  18. }
  19. var reader = new FileReader();
  20. reader.onload = function (e) {
  21. var content = e.target.result;
  22. // 处理上传的数据文件内容
  23. // 在这里,你可以解析数据文件(例如CSV文件)
  24. var data = parseCSVData(content);
  25. dataPoints = data;
  26. // 这里进行后续对数据的处理
  27. };
  28. reader.readAsText(file);

再看<上传并插值按钮>。这个按钮做的就是通过数据文件解析得到的数据进行插值,并将插值结果画出来。解析文件功能已经实现了,还差通过数据点插值和展示插值结果两个功能。通过数据点插值通过python实现,需要结合flask,这个后面再说。展示插值结果,本质就是将python处理好的结果画出来,这个简单,导入一个第三方js库Ployly就可以通过少量代码实现了。

  1. function Plot(input) {
  2. var dataPoints = input.dataPoints
  3. var interpolatedData = input.interpolatedData
  4. var interpType = input.interpType
  5. // 创建图表数据
  6. chartData = [{
  7. x: dataPoints.x,
  8. y: dataPoints.y,
  9. mode: 'markers',
  10. type: 'scatter',
  11. name: '数据点'
  12. }, {
  13. x: interpolatedData.x,
  14. y: interpolatedData.y,
  15. mode: 'lines',
  16. type: 'scatter',
  17. name: '插值曲线'
  18. }];
  19. // 创建图表
  20. var layout = {
  21. title: interpType,
  22. xaxis: {
  23. title: 'X轴'
  24. },
  25. yaxis: {
  26. title: 'Y轴'
  27. }
  28. };
  29. Plotly.newPlot('chart', chartData, layout);
  30. }

<插值并下载>按钮就类似了,这里就不说了。

<清空图像>按钮,顾名思义,把画好的图像清除,这个也简单。

  1. function clearChart() {
  2. Plotly.purge('chart');
  3. }

最后将函数绑定相应的按钮即可。

五、后端实现

前面也说到了,插值的算法还是得用python来实现,这就涉及到前后端的交互了。大致意思就是将前端数据传到后端,后端处理之后再传回前端。这里主要的问题就是怎么把解析好的数据传到python中,可以用JavaScript和Ajax来实现。先创建一个app.py,写上一些基本的东西。

  1. from flask import Flask, render_template, request, jsonify
  2. import numpy as np
  3. from scipy.interpolate import CubicSpline
  4. app = Flask(__name__)
  5. @app.route('/')
  6. def home_page():
  7. return render_template("index.html")
  8. @app.route('/index.html')
  9. def index():
  10. return render_template("index.html")
  11. if __name__ == "__main__":
  12. app.run(host='0.0.0.0', port=5000, debug=True)

如果将前面的html命名为index.html,js函数命名为show.js,通过以下目录结构来存放:

/主目录

        -static

                -show.js

        -templates

                -index.html

        -app.py

 运行app.py之后,可以得到如下输出:

  1. * Serving Flask app 'app'
  2. * Debug mode: on
  3. WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
  4. * Running on all addresses (0.0.0.0)
  5. * Running on http://127.0.0.1:5000
  6. * Running on http://{你的IP地址}:5000
  7. Press CTRL+C to quit
  8. * Restarting with stat
  9. * Debugger is active!
  10. * Debugger PIN: 126-643-674

这时,如果在浏览器中输入http://127.0.0.1:5000就可以得到我们刚才写好的html界面了。

现在再来实现插值算法的函数。给个路由名/process_input。

  1. @app.route('/process_input', methods=['POST'])
  2. def process_input():
  3. input = request.get_json()
  4. dataPoints = input.get('dataPoints', '')
  5. boundaryCondition = input.get('boundaryCondition', '')
  6. leftBoundary = float(input.get('leftBoundary', ''))
  7. rightBoundary = float(input.get('rightBoundary', ''))
  8. x = dataPoints['x']
  9. y = dataPoints['y']
  10. # 使用CubicSpline进行三次样条插值
  11. if boundaryCondition == "I型":
  12. cs = CubicSpline(x, y, bc_type=((1, leftBoundary), (1, rightBoundary)))
  13. elif boundaryCondition == "II型":
  14. cs = CubicSpline(x, y, bc_type=((2, leftBoundary), (2, rightBoundary)))
  15. else:
  16. cs = CubicSpline(x, y)
  17. # 生成插值点
  18. x_interp = np.linspace(np.min(x), np.max(x), 100)
  19. y_interp = cs(x_interp)
  20. return jsonify({"interpolatedData": {'x': list(x_interp), 'y': list(y_interp)}})
@app.route('/process_input', methods=['POST'])

这个就表示函数process_input是在路由/process_input下,仅接受POST请求的函数。

input = request.get_json()

这个就表示获取前端发送的数据到input中,是一个字典类型。

return jsonify({"interpolatedData": {'x': list(x_interp), 'y': list(y_interp)}})

这个就表示返回处理好的数据,也是一个字典类型。

有了对数据进行插值的函数,接下来才到了如何传数据给后端。用JavaScript和Ajax。

  1. function senDataToPython(input) {
  2. var dataPoints = input.dataPoints
  3. var boundaryCondition = document.getElementById("boundary-condition").value;
  4. var leftBoundary = document.getElementById("leftBoundaryCondition").value;
  5. var rightBoundary = document.getElementById("rightBoundaryCondition").value;
  6. if (dataPoints.x.length < 2 | dataPoints.y.length < 2) {
  7. alert("请提供至少两个数据点。");
  8. return;
  9. }
  10. var xhr = new XMLHttpRequest();
  11. xhr.open("POST", "/process_input", true);
  12. xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
  13. xhr.onreadystatechange = function () {
  14. if (xhr.readyState === 4 && xhr.status === 200) {
  15. var response = JSON.parse(xhr.responseText);
  16. var interpolatedData = response.interpolatedData
  17. //这里对从后端发送来的数据做进一步处理
  18. }
  19. };
  20. xhr.send(JSON.stringify({ dataPoints: dataPoints, boundaryCondition: boundaryCondition,
  21. leftBoundary: leftBoundary, rightBoundary: rightBoundary }));
  22. }
var dataPoints = input.dataPoints

dataPoints表示解析csv数据文件得到的数据。

至此呢,所有主体工作就全部完成了!首先上传数据文件,接着解析数据文件,再将数据文件传给后端处理,返回处理结果,最后展示处理后的结果。整个流程下来,基本需要实现的功能都实现了,就差将他们整合在一块了,这就没啥技术含量了,先看看最终效果吧!

效果还是不错的,能跑(哈哈) 。

六、写在最后

文字还是难以描述清楚,想要进一步了解的可以去下载所有的源码,互相交流学习。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/66512?site
推荐阅读
相关标签
  

闽ICP备14008679号