当前位置:   article > 正文

【Python成长之路】基于Flask-admin库,结合html+vue,实现前后端数据传递_flask admin

flask admin

一、前言

前面已经做了Flask-admin库的基本介绍和几个库常用功能如何使用,若不了解请移步到以下博客:

1、?《【Python成长之路】基于Flask-admin库,编写个人工作平台代码详述》

2、?《【Python成长之路】基于Flask-admin库,编写个人工作平台代码 -- 进阶版》

此篇文章主要是讲述:

1、结合pyecharts库实现图表展示

2、结合flask+html+vue,实现后端数据在前端界面展示,以表格为例

3、结合flask+html+vue,实现前端界面数据回传后端

其中各功能效果如下图

1、如何结合pyecharts库实现图表展示

image-20230505201234668

image-20230505201123801

2、前端数据展示

image-20230505203918283

3、前端表单数据回传到后台

image-20230505215920855

二、图表展示

1、增加数据库类和视图类

由于这里已经在之前文章讲过了,因此不再复述。直接上代码

  1. # 新增价格数据库类 
  2. class Price(db.Model):
  3.     id = db.Column(db.Integer, primary_key=True)
  4.     type = db.Column(db.Unicode(64))
  5.     price = db.Column(db.Float(64))
  6.     def __unicode__(self):
  7.         return self.name
  8. # 新增价格表的视图类
  9. class PriceAdmin(CustomView):
  10.     column_searchable_list = ('price''type')
  11.  
  12.     # 添加自定义功能:绘制图表
  13.     from flask_admin.actions import action
  14.     @action('figure''绘制曲线图',)
  15.     def action_approve(self, ids):
  16.         fruits = []
  17.         prices = []
  18.         for id in ids:
  19.             tmp = query_data_by_id(int(id), table='price', mydb='instance\\sample_db.sqlite')
  20.             fruits.append(tmp[1])
  21.             prices.append(tmp[2])
  22.         # myline为自定义的画图函数,下面重点介绍
  23.         myline(fruits,prices)
  24.         return render_template("line.html")

2、利用pyecharts库生成图表

首先介绍下 pyecharts官方指导文档:https://pyecharts.org/#/zh-cn/intro

本文即使用Line图进行绘制图表,详细代码如下:

  1. from pyecharts.charts import Line
  2. from pyecharts.globals import CurrentConfig
  3. from pyecharts import options as opts
  4. import os
  5. CurrentConfig.ONLINE_HOST = "https://cdn.jsdelivr.net/npm/echarts@latest/dist/"
  6. def myline(x, y):
  7.     line = Line()
  8.     line.add_xaxis(x)
  9.     line.add_yaxis('价格', y)
  10.     line.set_global_opts(title_opts=opts.TitleOpts(title="Line-基本示例", subtitle="价格表"))
  11.     html_path = os.path.join(os.getcwd(), 'templates''line.html')
  12.     print(html_path)
  13.     line.render(html_path)

这里要解释下 ,为什么需要添加

CurrentConfig.ONLINE_HOST = "https://cdn.jsdelivr.net/npm/echarts@latest/dist/"

主要原因是如果不加这个配置,通过flask-admin加载line.html时会特别慢,体验效果很不好。因此通过CDN加速改变了网页源代码。

三、结合flask+html+vue,将后端数据传到前端

1、Vue组件示例网站介绍

在使用vue前,提供一个vue示例官网,从里面可以快速实现常用前端界面组件

https://element.eleme.cn/#/zh-CN/component/installation

2、结合html+vue,实现前端helloworld展示

为了方便使用,直接采用CDN方式进行安装vue

另外,目前可以通过 ?unpkg.com/element-ui 获取到最新版本的资源,在页面上引入 js 和 css 文件即可开始使用。

helloworld.html代码样式如下 :

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.   <meta charset="UTF-8">
  5.   <!-- import CSS -->
  6.   <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  7. </head>
  8. <body>
  9.   <div id="app">
  10.     <el-button @click="visible = true">Button</el-button>
  11.     <el-dialog :visible.sync="visible" title="Hello world">
  12.       <p>Try Element</p>
  13.     </el-dialog>
  14.   </div>
  15. </body>
  16.   <!-- import Vue before Element -->
  17.   <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
  18.   <!-- import JavaScript -->
  19.   <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  20.   <script>
  21.     new Vue({
  22.       el: '#app',
  23.       datafunction() {
  24.         return { visible: false }
  25.       }
  26.     })
  27.   </script>
  28. </html>

3、编写前端示例代码(表格)

参考https://element.eleme.cn/#/zh-CN/component/table 章节,修改helloworld.html,实现前端表格代码。

主要是将

和script中 的内容进行重新编写。

table.html代码如下:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <!-- import CSS -->
  6.     <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  7. </head>
  8. <body>
  9. <div id="app">
  10.     <template>
  11.         <el-table
  12.                 :data="tableData"
  13.                 style="width: 100%">
  14.             <el-table-column
  15.                     prop="date"
  16.                     label="日期"
  17.                     width="180">
  18.             </el-table-column>
  19.             <el-table-column
  20.                     prop="name"
  21.                     label="姓名"
  22.                     width="180">
  23.             </el-table-column>
  24.             <el-table-column
  25.                     prop="address"
  26.                     label="地址">
  27.             </el-table-column>
  28.         </el-table>
  29.     </template>
  30. </div>
  31. </body>
  32. <!-- import Vue before Element -->
  33. <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
  34. <!-- import JavaScript -->
  35. <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  36. <script>
  37.     new Vue({
  38.       el: '#app',
  39.         data() {
  40.         return {
  41.           tableData: [{
  42.             date'2016-05-02',
  43.             name: '王小虎',
  44.             address'上海市普陀区金沙江路 1518 弄'
  45.           }]
  46.         }
  47.       }
  48.     })
  49. </script>
  50. </html>

效果如下 :

image-20230505203918283

4、将后端数据传给前端并以表格形式展示

通过分析table.html可以发现,如果想要将后端数据传给前端并展示,关键是将script中的tableData内容进行更换,而这最简单的方式即通过{ datasafe }方式进行传递和赋值。

后端python代码

下面只是简单介绍如何将后端数据进行传递,实际应用中data应为数据库数据或者其他数据。

  1.     @action('table''前端表格展示', )
  2.     def action_table(self, ids):
  3.         data = [{
  4.             'date''2023/05/05',
  5.             'name''鹏哥',
  6.             'address''test123456789'
  7.           }]
  8.         # 将data数据进行入参传给table.html
  9.         return render_template('table.html',data=data)

前端html代码

  1. # 其他都不变,仅变更tableData数据内容,通过{{ data|safe }}进行赋值
  2. <script>
  3.     new Vue({
  4.       el'#app',
  5.         data() {
  6.         return {
  7.           tableData{{ data|safe}}
  8.         }
  9.       }
  10.     })
  11. </script>

效果如下:

image-20230505204827718

四、结合flask+html+vue,将前端数据传到后端

1、结合html+vue,编写前端示例代码(表单)

参考https://element.eleme.cn/#/zh-CN/component/form,实现前端表单展示

form.html代码示例如下

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <!-- import CSS -->
  6.     <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  7. </head>
  8. <body>
  9. <div id="app">
  10.     <el-form ref="form" :model="form" label-width="80px">
  11.         <el-form-item label="活动名称">
  12.             <el-input v-model="form.name"></el-input>
  13.         </el-form-item>
  14.         <el-form-item label="活动区域">
  15.             <el-select v-model="form.region" placeholder="请选择活动区域">
  16.                 <el-option label="区域一" value="shanghai"></el-option>
  17.                 <el-option label="区域二" value="beijing"></el-option>
  18.             </el-select>
  19.         </el-form-item>
  20.         <el-form-item label="活动时间">
  21.             <el-col :span="11">
  22.                 <el-date-picker type="date" placeholder="选择日期" v-model="form.date1"
  23.                                 style="width: 100%;"></el-date-picker>
  24.             </el-col>
  25.             <el-col class="line" :span="2">-</el-col>
  26.             <el-col :span="11">
  27.                 <el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
  28.             </el-col>
  29.         </el-form-item>
  30.         <el-form-item label="即时配送">
  31.             <el-switch v-model="form.delivery"></el-switch>
  32.         </el-form-item>
  33.         <el-form-item label="活动性质">
  34.             <el-checkbox-group v-model="form.type">
  35.                 <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
  36.                 <el-checkbox label="地推活动" name="type"></el-checkbox>
  37.                 <el-checkbox label="线下主题活动" name="type"></el-checkbox>
  38.                 <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
  39.             </el-checkbox-group>
  40.         </el-form-item>
  41.         <el-form-item label="特殊资源">
  42.             <el-radio-group v-model="form.resource">
  43.                 <el-radio label="线上品牌商赞助"></el-radio>
  44.                 <el-radio label="线下场地免费"></el-radio>
  45.             </el-radio-group>
  46.         </el-form-item>
  47.         <el-form-item label="活动形式">
  48.             <el-input type="textarea" v-model="form.desc"></el-input>
  49.         </el-form-item>
  50.         <el-form-item>
  51.             <el-button type="primary" @click="onSubmit">立即创建</el-button>
  52.             <el-button>取消</el-button>
  53.         </el-form-item>
  54.     </el-form>
  55. </div>
  56. </body>
  57. <!-- import Vue before Element -->
  58. <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
  59. <!-- import JavaScript -->
  60. <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  61. <script>
  62.     new Vue({
  63.       el: '#app',
  64.         data() {
  65.       return {
  66.         form: {
  67.           name: '',
  68.           region: '',
  69.           date1'',
  70.           date2'',
  71.           delivery: false,
  72.           type: [],
  73.           resource: '',
  74.           desc: ''
  75.         }
  76.       }
  77.     },
  78.     methods: {
  79.       onSubmit() {
  80.         this.$alert('submit!');
  81.       }
  82.     }
  83.     })
  84. </script>
  85. </html>

效果如下 :

image-20230505210420402

2、编写前端axios方法及参数

从form.html代码中可 以爬到,立即创建按钮当前仅会弹窗功能,并未实现将数据往后端传递功能。

因此需要在前面使用axios发起请求。

本来想是参考以下代码实现axios请求,但是测试发现并不生效,并且报错: axios.post is not a function

  1. onSubmit() {
  2.  this.axios({
  3.   method'post',
  4.   url'/test',
  5.   data: {'aa':123},
  6.  })
  7.  .then((response) => {
  8.         console.log(response)
  9.  })
  10.  .catch((error) => {
  11.   console.log(error)
  12.  })
  13. },

定位发现是缺少安装axios。为了方便使用,继续使用CDN方式,即在script中添加

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

最终form.html内容如下:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <!-- import CSS -->
  6.     <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  7. </head>
  8. <body>
  9. <div id="app">
  10.     <el-form ref="form" :model="form" label-width="80px">
  11.         <el-form-item label="活动名称" prop="name">
  12.             <el-input v-model="form.name"></el-input>
  13.         </el-form-item>
  14.         <el-form-item label="活动区域" prop="region">
  15.             <el-select v-model="form.region" placeholder="请选择活动区域">
  16.                 <el-option label="区域一" value="shanghai"></el-option>
  17.                 <el-option label="区域二" value="beijing"></el-option>
  18.             </el-select>
  19.         </el-form-item>
  20.         <el-form-item label="活动时间">
  21.             <el-col :span="11">
  22.                 <el-date-picker type="date" placeholder="选择日期" v-model="form.date1"
  23.                                 style="width: 100%;"></el-date-picker>
  24.             </el-col>
  25.             <el-col class="line" :span="2">-</el-col>
  26.             <el-col :span="11">
  27.                 <el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
  28.             </el-col>
  29.         </el-form-item>
  30.         <el-form-item label="即时配送" prop="delivery">
  31.             <el-switch v-model="form.delivery"></el-switch>
  32.         </el-form-item>
  33.         <el-form-item label="活动性质" prop="type">
  34.             <el-checkbox-group v-model="form.type">
  35.                 <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
  36.                 <el-checkbox label="地推活动" name="type"></el-checkbox>
  37.                 <el-checkbox label="线下主题活动" name="type"></el-checkbox>
  38.                 <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
  39.             </el-checkbox-group>
  40.         </el-form-item>
  41.         <el-form-item label="特殊资源" prop="resource">
  42.             <el-radio-group v-model="form.resource">
  43.                 <el-radio label="线上品牌商赞助"></el-radio>
  44.                 <el-radio label="线下场地免费"></el-radio>
  45.             </el-radio-group>
  46.         </el-form-item>
  47.         <el-form-item label="活动形式" prop="desc">
  48.             <el-input type="textarea" v-model="form.desc"></el-input>
  49.         </el-form-item>
  50.         <el-form-item>
  51.             <el-button type="primary" @click="onSubmit">立即创建</el-button>
  52.             <el-button @click="resetForm('form')">重置</el-button>
  53.         </el-form-item>
  54.     </el-form>
  55. </div>
  56. </body>
  57. <!-- import Vue before Element -->
  58. <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
  59. <!-- import JavaScript -->
  60. <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  61. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  62. <script>
  63.     new Vue({
  64.       el: '#app',
  65.         data() {
  66.       return {
  67.         form: {
  68.           name: '',
  69.           region: '',
  70.           date1'',
  71.           date2'',
  72.           delivery: false,
  73.           type: [],
  74.           resource: '',
  75.           desc: ''
  76.         }
  77.       }
  78.     },
  79.     methods: {
  80.       onSubmit() {
  81.         axios({
  82.                 method'post',
  83.                 url: '/test',
  84.                 data: {
  85.                 'name':this.form.name,
  86.                 'region':this.form.region,
  87.                 },
  88.             })
  89.             .then((response) => {
  90.                 console.log(response)
  91.             })
  92.             .catch((error=> {
  93.                 console.log(error)
  94.             })
  95.     },
  96.           resetForm(formName) {
  97.         this.$refs[formName].resetFields();
  98.       }
  99.     }
  100.     })
  101. </script>
  102. </html>

这里再补充说明下,回传数据data的内容,即name/region都是form中定义好的。当前仅以name/region参数做演示,所有字段都可以进行传递。

另外,重置功能可以简单地通过以下代码实现,但是有2个前置条件:

1、form组件上必须要有ref

2、form-item上必须要有prop属性

  1. # body中重置代码
  2. <el-button @click="resetForm('form')">重置</el-button>
  3. # script中重置代码
  4. this.$refs[formName].resetFields();

即需要body中有以下代码

  1. <el-form ref="form" :model="form" label-width="80px">
  2.     xxx
  3. <el-form-item label="活动名称" prop="name">

3、后端获取数据

python代码如下

  1. from flask_cors import CORS
  2. from flask import request
  3. app = Flask(__name__)
  4. CORS(app, resources=r'/*')
  5. @app.route('/test', methods=['post''get'])
  6. def test():
  7.     if request.method == 'POST':
  8.         print("********** post *************")
  9.         data = request.get_json(silent=True)
  10.         # 获取数据后如何处理,可自行编写代码
  11.         print(data['name'])
  12.         print(data['region'])
  13.     return render_template('form.html')

其中,CORS是为了解决跨域问题。

五、完整代码获取

github地址如下:

https://github.com/yuzipeng05/flask_admin_work_platform

FAQ

1、报错:jinja2.exceptions.TemplateSyntaxError: unexpected char '\' at 1100277

image-20230422144135217

问题定位:通过升级pyecharts版本至最新版本解决;

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

闽ICP备14008679号