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

news2024/12/22 22:21:18

一、前言

前面已经做了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、增加数据库类和视图类

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

# 新增价格数据库类 
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")

2、利用pyecharts库生成图表

首先介绍下 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加速改变了网页源代码。

三、结合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代码样式如下 :

<!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>

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

参考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

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

通过分析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

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

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

参考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

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

从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">

3、后端获取数据

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

FAQ

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

image-20230422144135217

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/493449.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DP练习题

1.减操作(ACWING) 若有 a b c d e f g 几个数&#xff0c; 先对位置d操作 变成 a b c d - e f g 再对c操作 变成 a b c - (d-e) f g 仔细分析后得出结论&#xff1a;对于第一个数如a, 它一定为正数&#xff0c;第二个数b,一定为负数&#…

Java并发(四)----线程运行原理

1、线程运行原理 1.1 栈与栈帧   Java Virtual Machine Stacks &#xff08;Java 虚拟机栈 JVM&#xff09; 我们都知道 JVM 中由堆、栈、方法区所组成&#xff0c;其中栈内存是给谁用的呢&#xff1f;其实就是线程&#xff0c;每个线程启动后&#xff0c;虚拟机就会为其分…

java 解密springboot的WEB端口是谁启动的之内嵌tomcat

找到项目的 pom.xml 看到下面的spring-boot-starter-web 我们按住 Ctrl 点击进去 里面就有一个 tomcat 简单说 我们的程序能启动起tomcat端口 就是靠的这个东西 简单说 就是在程序中嵌了一个tomcat服务器 这里 可能就有小伙伴蒙了 不是把程序放在服务器上运行吗&#xff1f…

Linux Driver 和Device匹配过程分析(2)

Linux Driver 和Device匹配过程分析&#xff08;2&#xff09; 1 device注册流程2&#xff0c;driver注册匹配过程&#xff1a;2.1 pci_register_driver2.1.1 nvme_init2.1.2 pci_register_driver2.1.3 __pci_register_driver2.1.4 driver_register2.1.5 bus_add_driver2.1.6 d…

读书笔记——《2001太空漫游》

阿瑟克拉克神作&#xff0c;任何一个科幻迷都绕不开的一部作品。很早就听说过其大名&#xff0c;因为之前看过电影版的&#xff0c;总感觉少了点新鲜感&#xff0c;这本书就一直在书架上没有拿出来看。但是看过这本书后&#xff0c;我可以很负责任的说&#xff0c;全书都充满新…

【递推专题】常见的递推“模型”总结

目录 1.斐波那契数列分析&#xff1a;代码&#xff1a; 2.平面分割问题分析&#xff1a; 3.汉诺塔问题分析&#xff1a; 4.卡特兰数分析&#xff1a; 5.第二类斯特林数总结&#xff1a; 1.斐波那契数列 分析&#xff1a; 斐波那契数列又称兔子数列&#xff0c;其原理来源于兔子…

dangerousRemoteUrlIpcAccess

问题描述&#xff1a; 在使用Tauri窗口加载外部链接时&#xff0c;需要也能继续使用Tauri API与Rust交互。按照官方发布通告中的代码添加配置&#xff1a; "security": {"dangerousRemoteUrlIpcAccess": [ { "windows": ["main", &qu…

在Linux中进行Jenkins部署(maven-3.9.1+jdk8)

Jenkins部署在公网IP为x.x.x.x的服务器上 maven-3.9.1要安装在jdk8环境中 环境准备 第一步&#xff0c;下载server-jre-8u202-linux-x64.tar.gz安装包。 登录地址&#xff1a;https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html下载server-j…

Maven命令和配置详解

Maven命令和配置详解 1. pom基本结构2. build基本结构3. Maven命令详解3.1 打包命令3.2 常用命令3.3 批量修改版本-父子pom4. Maven配置详解4.1 settings.xml4.2 项目内的maven工程结构Maven POM构建生命周期工程实践1. pom基本结构 <?xml versi

《程序员面试金典(第6版)》面试题 16.13. 平分正方形(直线的斜截式方程,C++)

题目描述 给定两个正方形及一个二维平面。请找出将这两个正方形分割成两半的一条直线。假设正方形顶边和底边与 x 轴平行。 每个正方形的数据square包含3个数值&#xff0c;正方形的左下顶点坐标[X,Y] [square[0],square[1]]&#xff0c;以及正方形的边长square[2]。所求直线穿…

JDK8 中Arrays.sort() 排序方法解读

一、引言 在刷算法的时候经常需要对数组进行排序&#xff0c;第一反应就是直接使用java.util包下的Arrays.sort()方法直接排序。但在刷算法时会通过时间复杂度和空间复杂度对实现的算法进行评价&#xff0c;因此我们需对Arrays.sort()方法有所了解。 本文先行介绍Arrays.sort…

图的基本概念和术语

图&#xff1a;G&#xff08;V,E&#xff09; V:顶点&#xff08;数据元素&#xff09;的又穷非空集合&#xff1b; E:边的有穷集合。 无向图&#xff1a;每条边都是无方向的G2 有向图&#xff1a; 每条边都是有方向的G1 完全图&#xff1a;任意两个点都有一条边相连 假设…

使用rollup打包ts+react缓存组件发布npm

新建一个项目目录比如叫root,下面新建一个rollup的配置文件: rollup.config.ts 因为rollup良好支持ts和esmodule 所以用ts配置文件 Setup 生成一个package.json文件,这里用pnpm生成: pnpm init安装rollup和Typescript: pnpm add rollup pnpm add typescript配置package.jso…

Android 自定义View 之 简易输入框

简易输入框 前言正文① 构造方法② XML样式③ 测量④ 绘制1. 绘制方框2. 绘制文字 ⑤ 输入1. 键盘布局2. 键盘接口3. 键盘弹窗4. 显示键盘5. 相关API 四、使用自定义View五、源码 前言 在日常工作开发中&#xff0c;我们时长会遇到各种各样的需求&#xff0c;不部分需求是可以通…

在云服务器上部署jupyter服务

1.准备一台云服务器&#xff0c;阿里云、腾讯云都可以&#xff0c;并且远程登陆&#xff0c;在云服务器的安全组中配置8888的访问端口&#xff0c;因为jupyter默认的访问端口是8888&#xff0c;如下述步骤&#xff1b;以阿里云服务器的centos系统为例 2.使用以下命令在服务器…

golang 微服务容错处理是如何做的?

随着微服务的规模越来越大&#xff0c;各个微服务之间可能会存在错综复杂的调用关系 在我们实际工作中&#xff0c;确实慢慢的也出现了很多问题&#xff0c;整个系统的弊端的慢慢的展现出来 例如就会有这样的情况&#xff1a; 服务 A 去请求服务B&#xff0c;服务 B 还需要去…

HTB-Silo

HTB-Silo 信息收集立足root哈希传递攻击 信息收集 分别对smb和rpc都进行guest用户和空密码测试。 1521的Oracle TNS listener 11.2.0.2.0。 搜索可能存在的漏洞。 得到一个CVE编号cve-2012-1675。同时我们可以对其进行SID枚举&#xff0c;SID说简单点就是数据库的名字。 简单…

错题汇总04

1.以下C语言指令&#xff1a; int a[5] {1,3,5,7,9}; int *p (int *)(&a1); printf(“%d,%d”,*(a1)&#xff0c;*(p-1)); 运行结果是什么&#xff1f; A 2,1 B 3,1 C 3,9 D 运行时崩溃 数组名只有在&与sizeof之后&#xff0c;才表明数组本身&#xff0c;其余表…

平均情况时间复杂度

// n表示数组array的长度 int find(int[] array, int n, int x) {int i 0;int pos -1;for (; i < n; i) {if (array[i] x){ pos i; break;}}return pos; } 通过以上代码&#xff0c;我们分析一下平均情况时间复杂度。 以上代码要查找的变量 x 在数组中的位置&#xff…

并发编程02:CompletableFuture

文章目录 2.1 Future接口理论知识2.2 Future接口常用实现类FutureTask异步任务2.2.1 Future接口能干什么2.2.2 Future接口相关架构2.2.3 Future编码实战和优缺点分析2.2.4 完成一些复杂的任务 2.3 CompletableFuture对Future的改进2.3.1 CompletableFuture为什么会出现2.3.2 Co…