赞
踩
前面已经做了Flask-admin库的基本介绍和几个库常用功能如何使用,若不了解请移步到以下博客:
1、?《【Python成长之路】基于Flask-admin库,编写个人工作平台代码详述》
2、?《【Python成长之路】基于Flask-admin库,编写个人工作平台代码 -- 进阶版》
此篇文章主要是讲述:
其中各功能效果如下图
1、如何结合pyecharts库实现图表展示
image-20230505201234668
image-20230505201123801
2、前端数据展示
image-20230505203918283
3、前端表单数据回传到后台
image-20230505215920855
由于这里已经在之前文章讲过了,因此不再复述。直接上代码
- # 新增价格数据库类
- class Price(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- type = db.Column(db.Unicode(64))
- price = db.Column(db.Float(64))
-
- def __unicode__(self):
- return self.name
-
- # 新增价格表的视图类
- class PriceAdmin(CustomView):
- column_searchable_list = ('price', 'type')
-
- # 添加自定义功能:绘制图表
- from flask_admin.actions import action
- @action('figure', '绘制曲线图',)
- def action_approve(self, ids):
- fruits = []
- prices = []
- for id in ids:
- tmp = query_data_by_id(int(id), table='price', mydb='instance\\sample_db.sqlite')
- fruits.append(tmp[1])
- prices.append(tmp[2])
- # myline为自定义的画图函数,下面重点介绍
- myline(fruits,prices)
- return render_template("line.html")
首先介绍下 pyecharts官方指导文档:https://pyecharts.org/#/zh-cn/intro
本文即使用Line图进行绘制图表,详细代码如下:
- from pyecharts.charts import Line
- from pyecharts.globals import CurrentConfig
- from pyecharts import options as opts
- import os
-
- CurrentConfig.ONLINE_HOST = "https://cdn.jsdelivr.net/npm/echarts@latest/dist/"
-
- def myline(x, y):
- line = Line()
- line.add_xaxis(x)
- line.add_yaxis('价格', y)
- line.set_global_opts(title_opts=opts.TitleOpts(title="Line-基本示例", subtitle="价格表"))
- html_path = os.path.join(os.getcwd(), 'templates', 'line.html')
- print(html_path)
- line.render(html_path)
这里要解释下 ,为什么需要添加
CurrentConfig.ONLINE_HOST = "https://cdn.jsdelivr.net/npm/echarts@latest/dist/"
主要原因是如果不加这个配置,通过flask-admin加载line.html时会特别慢,体验效果很不好。因此通过CDN加速改变了网页源代码。
在使用vue前,提供一个vue示例官网,从里面可以快速实现常用前端界面组件
https://element.eleme.cn/#/zh-CN/component/installation
为了方便使用,直接采用CDN方式进行安装vue
另外,目前可以通过 ?unpkg.com/element-ui 获取到最新版本的资源,在页面上引入 js 和 css 文件即可开始使用。
helloworld.html代码样式如下 :
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <!-- import CSS -->
- <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
- </head>
- <body>
- <div id="app">
- <el-button @click="visible = true">Button</el-button>
- <el-dialog :visible.sync="visible" title="Hello world">
- <p>Try Element</p>
- </el-dialog>
- </div>
- </body>
- <!-- import Vue before Element -->
- <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
- <!-- import JavaScript -->
- <script src="https://unpkg.com/element-ui/lib/index.js"></script>
- <script>
- new Vue({
- el: '#app',
- data: function() {
- return { visible: false }
- }
- })
- </script>
- </html>
参考https://element.eleme.cn/#/zh-CN/component/table 章节,修改helloworld.html,实现前端表格代码。
主要是将
和script中 的内容进行重新编写。
table.html代码如下:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <!-- import CSS -->
- <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
- </head>
- <body>
- <div id="app">
- <template>
- <el-table
- :data="tableData"
- style="width: 100%">
- <el-table-column
- prop="date"
- label="日期"
- width="180">
- </el-table-column>
- <el-table-column
- prop="name"
- label="姓名"
- width="180">
- </el-table-column>
- <el-table-column
- prop="address"
- label="地址">
- </el-table-column>
- </el-table>
- </template>
- </div>
- </body>
- <!-- import Vue before Element -->
- <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
- <!-- import JavaScript -->
- <script src="https://unpkg.com/element-ui/lib/index.js"></script>
- <script>
- new Vue({
- el: '#app',
- data() {
- return {
- tableData: [{
- date: '2016-05-02',
- name: '王小虎',
- address: '上海市普陀区金沙江路 1518 弄'
- }]
- }
- }
- })
- </script>
- </html>
效果如下 :
image-20230505203918283
通过分析table.html可以发现,如果想要将后端数据传给前端并展示,关键是将script中的tableData内容进行更换,而这最简单的方式即通过{ datasafe }方式进行传递和赋值。
后端python代码
下面只是简单介绍如何将后端数据进行传递,实际应用中data应为数据库数据或者其他数据。
- @action('table', '前端表格展示', )
- def action_table(self, ids):
- data = [{
- 'date': '2023/05/05',
- 'name': '鹏哥',
- 'address': 'test123456789'
- }]
- # 将data数据进行入参传给table.html
- return render_template('table.html',data=data)
前端html代码
- # 其他都不变,仅变更tableData数据内容,通过{{ data|safe }}进行赋值
- <script>
- new Vue({
- el: '#app',
- data() {
- return {
- tableData: {{ data|safe}}
- }
- }
- })
- </script>
效果如下:
image-20230505204827718
参考https://element.eleme.cn/#/zh-CN/component/form,实现前端表单展示
form.html代码示例如下
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <!-- import CSS -->
- <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
- </head>
- <body>
- <div id="app">
- <el-form ref="form" :model="form" label-width="80px">
- <el-form-item label="活动名称">
- <el-input v-model="form.name"></el-input>
- </el-form-item>
- <el-form-item label="活动区域">
- <el-select v-model="form.region" placeholder="请选择活动区域">
- <el-option label="区域一" value="shanghai"></el-option>
- <el-option label="区域二" value="beijing"></el-option>
- </el-select>
- </el-form-item>
- <el-form-item label="活动时间">
- <el-col :span="11">
- <el-date-picker type="date" placeholder="选择日期" v-model="form.date1"
- style="width: 100%;"></el-date-picker>
- </el-col>
- <el-col class="line" :span="2">-</el-col>
- <el-col :span="11">
- <el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
- </el-col>
- </el-form-item>
- <el-form-item label="即时配送">
- <el-switch v-model="form.delivery"></el-switch>
- </el-form-item>
- <el-form-item label="活动性质">
- <el-checkbox-group v-model="form.type">
- <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
- <el-checkbox label="地推活动" name="type"></el-checkbox>
- <el-checkbox label="线下主题活动" name="type"></el-checkbox>
- <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
- </el-checkbox-group>
- </el-form-item>
- <el-form-item label="特殊资源">
- <el-radio-group v-model="form.resource">
- <el-radio label="线上品牌商赞助"></el-radio>
- <el-radio label="线下场地免费"></el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="活动形式">
- <el-input type="textarea" v-model="form.desc"></el-input>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="onSubmit">立即创建</el-button>
- <el-button>取消</el-button>
- </el-form-item>
- </el-form>
- </div>
- </body>
- <!-- import Vue before Element -->
- <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
- <!-- import JavaScript -->
- <script src="https://unpkg.com/element-ui/lib/index.js"></script>
- <script>
- new Vue({
- el: '#app',
- data() {
- return {
- form: {
- name: '',
- region: '',
- date1: '',
- date2: '',
- delivery: false,
- type: [],
- resource: '',
- desc: ''
- }
- }
- },
- methods: {
- onSubmit() {
- this.$alert('submit!');
- }
- }
- })
-
- </script>
- </html>
效果如下 :
image-20230505210420402
从form.html代码中可 以爬到,立即创建按钮当前仅会弹窗功能,并未实现将数据往后端传递功能。
因此需要在前面使用axios发起请求。
本来想是参考以下代码实现axios请求,但是测试发现并不生效,并且报错: axios.post is not a function
- onSubmit() {
- this.axios({
- method: 'post',
- url: '/test',
- data: {'aa':123},
- })
- .then((response) => {
- console.log(response)
- })
- .catch((error) => {
- console.log(error)
- })
- },
-
定位发现是缺少安装axios。为了方便使用,继续使用CDN方式,即在script中添加
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
最终form.html内容如下:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <!-- import CSS -->
- <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
- </head>
- <body>
- <div id="app">
- <el-form ref="form" :model="form" label-width="80px">
- <el-form-item label="活动名称" prop="name">
- <el-input v-model="form.name"></el-input>
- </el-form-item>
- <el-form-item label="活动区域" prop="region">
- <el-select v-model="form.region" placeholder="请选择活动区域">
- <el-option label="区域一" value="shanghai"></el-option>
- <el-option label="区域二" value="beijing"></el-option>
- </el-select>
- </el-form-item>
- <el-form-item label="活动时间">
- <el-col :span="11">
- <el-date-picker type="date" placeholder="选择日期" v-model="form.date1"
- style="width: 100%;"></el-date-picker>
- </el-col>
- <el-col class="line" :span="2">-</el-col>
- <el-col :span="11">
- <el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
- </el-col>
- </el-form-item>
- <el-form-item label="即时配送" prop="delivery">
- <el-switch v-model="form.delivery"></el-switch>
- </el-form-item>
- <el-form-item label="活动性质" prop="type">
- <el-checkbox-group v-model="form.type">
- <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
- <el-checkbox label="地推活动" name="type"></el-checkbox>
- <el-checkbox label="线下主题活动" name="type"></el-checkbox>
- <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
- </el-checkbox-group>
- </el-form-item>
- <el-form-item label="特殊资源" prop="resource">
- <el-radio-group v-model="form.resource">
- <el-radio label="线上品牌商赞助"></el-radio>
- <el-radio label="线下场地免费"></el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="活动形式" prop="desc">
- <el-input type="textarea" v-model="form.desc"></el-input>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="onSubmit">立即创建</el-button>
- <el-button @click="resetForm('form')">重置</el-button>
- </el-form-item>
- </el-form>
- </div>
- </body>
- <!-- import Vue before Element -->
- <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
- <!-- import JavaScript -->
- <script src="https://unpkg.com/element-ui/lib/index.js"></script>
- <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
- <script>
- new Vue({
- el: '#app',
- data() {
- return {
- form: {
- name: '',
- region: '',
- date1: '',
- date2: '',
- delivery: false,
- type: [],
- resource: '',
- desc: ''
- }
- }
- },
- methods: {
- onSubmit() {
- axios({
- method: 'post',
- url: '/test',
- data: {
- 'name':this.form.name,
- 'region':this.form.region,
- },
- })
- .then((response) => {
- console.log(response)
- })
- .catch((error) => {
- console.log(error)
- })
- },
- resetForm(formName) {
- this.$refs[formName].resetFields();
- }
- }
- })
- </script>
- </html>
这里再补充说明下,回传数据data的内容,即name/region都是form中定义好的。当前仅以name/region参数做演示,所有字段都可以进行传递。
另外,重置功能可以简单地通过以下代码实现,但是有2个前置条件:
1、form组件上必须要有ref
2、form-item上必须要有prop属性
- # body中重置代码
- <el-button @click="resetForm('form')">重置</el-button>
-
- # script中重置代码
- this.$refs[formName].resetFields();
即需要body中有以下代码
- <el-form ref="form" :model="form" label-width="80px">
- xxx
- <el-form-item label="活动名称" prop="name">
python代码如下
- from flask_cors import CORS
- from flask import request
-
- app = Flask(__name__)
- CORS(app, resources=r'/*')
-
- @app.route('/test', methods=['post', 'get'])
- def test():
- if request.method == 'POST':
- print("********** post *************")
- data = request.get_json(silent=True)
- # 获取数据后如何处理,可自行编写代码
- print(data['name'])
- print(data['region'])
- return render_template('form.html')
其中,CORS是为了解决跨域问题。
github地址如下:
https://github.com/yuzipeng05/flask_admin_work_platform
1、报错:jinja2.exceptions.TemplateSyntaxError: unexpected char '\' at 1100277
image-20230422144135217
问题定位:通过升级pyecharts版本至最新版本解决;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。