当前位置: 首页 > news >正文

从0开始搭建vue + flask 旅游景点数据分析系统(七):可视化前后端对接实现

这一期继续编写flask后端,并且完成echarts折线图、柱状图和饼图的对接。

1 新增一些依赖

pip install Flask-SQLAlchemy Flask-Marshmallow pymysql

修改 init.py文件,下面给出完整代码:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallowdb = SQLAlchemy()
ma = Marshmallow()def create_app():app = Flask(__name__)app.config.from_object('app.config.Config')db.init_app(app)ma.init_app(app)from .routes import main as main_blueprintapp.register_blueprint(main_blueprint)return app

这里还加入了数据库的配置信息,需要修改app.config:

class Config:# scrapy_demo 就是之前旅游爬虫教程中建的数据库,如果不清楚,可以去看这个教程# 视频:https://www.bilibili.com/video/BV1Vx4y147wQ# 博客:https://blog.csdn.net/roccreed?type=blogSQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:12345678@localhost/scrapy_demo?charset=utf8'SQLALCHEMY_TRACK_MODIFICATIONS = False

2 后端模型

通过模型,可以在Flask后端系统里以面向对象的形式来操作数据库里的数据。

首先,新建app/models.py:

from . import dbclass Tour(db.Model):__tablename__ = 'tb_tour'id = db.Column(db.Integer, primary_key=True)title = db.Column(db.String(255), nullable=False)title_en = db.Column(db.String(255))img = db.Column(db.String(255))score = db.Column(db.Float)comments = db.Column(db.Integer)comment_url = db.Column(db.String(255))rank_title = db.Column(db.String(255))ranks = db.Column(db.Integer)select_user = db.Column(db.String(255))select_comment = db.Column(db.Text)nation = db.Column(db.String(255))city = db.Column(db.String(255))

创建schemas.py 文件,作用是数据在发送给前端的时候进行序列化,新建app/schemas.py:

from . import ma
from .models import Tourclass TourSchema(ma.SQLAlchemyAutoSchema):class Meta:model = Tourload_instance = Truetour_schema = TourSchema()
tours_schema = TourSchema(many=True)

修改routes.py 文件:

from flask import Blueprint, jsonifyfrom app.models import Tour
from app.schemas import tours_schemamain = Blueprint('main', __name__)# 这个测试的后面就不需要了,可以删除
@main.route('/test', methods=['GET'])
def test():data = [{'id': 1, 'name': 'John'}, {'id': 2, 'name': 'Jane'}]return jsonify(data)# 十大热门景点
@main.route('/commentsRank', methods=['GET'])
def getCommentsRank():top_tours = Tour.query.order_by(Tour.comments.desc()).limit(10).all()return tours_schema.jsonify(top_tours)

3 测试一下

在浏览器里输入 localhost:8080/commentsRank 访问,得到如下结果:

可以看到,访问后端是可以获取到数据的。
在这里插入图片描述

4 返回封装

在开始和前端对接前,先对后端的返回进行一定的优化

创建app/utils.py 文件

from flask import jsonifydef make_response(data=None, code=0, message='Success'):response = {'code': code,'message': message,'data': data if data is not None else []}return jsonify(response)

修改routes.py,之前测试的方法这边删除了:


# 十大热门景点(按照评论数排名)
@main.route('/top-tours', methods=['GET'])
def get_top_tours():try:top_tours = Tour.query.order_by(Tour.comments.desc()).limit(10).all()result = tours_schema.dump(top_tours)return make_response(data=result)except Exception as e:return make_response(code=1, message=str(e))

在测试一下,就可以发现结果封装在data里面了。

然后,下一步编写前端文件。

5 折线图的对接

上一小节已经写好了折线图的后端代码,现在开始写前端代码,修改LineChart.vue,这边我给出完整的源码了,另外两个图我只给出修改部分源码,因为原本的data部分不需要做任何修改:

<template><div><v-chart :option="chartOptions" style="width: 100%; height: 300px;"></v-chart></div>
</template><script>
import {getCommentsRank} from "@/api/tour"export default {name: 'TouristSpotRanking',data() {return {chartOptions: {title: {text: '旅游景点评论排名',},tooltip: {trigger: 'axis',},legend: {data: ['评论数'],},xAxis: {type: 'category',data: ['景点A', '景点B', '景点C', '景点D', '景点E'],},yAxis: {type: 'value',},series: [{name: '评论数',type: 'line',data: [820, 932, 901, 934, 1290],},],},};},mounted() {getCommentsRank().then(res => {console.log(res.data.data);this.chartOptions.xAxis.data = res.data.data.map(item => item.title);this.chartOptions.series[0].data = res.data.data.map(item => item.comments);})}
};
</script><style scoped>
/* 添加一些样式使图表看起来更好 */
</style>

在tour.js中添加方法:

// 排名前十的景点
export function getCommentsRank() {return request({url:  '/commentsRank',method: 'get'})
}

实现效果如下,可以看到景点按照评论数的折线图:
在这里插入图片描述

6 柱状图的对接

tour.js中添加方法:

// 按照城市排名
export function getCityRank() {return request({url:  '/cityRank',method: 'get'})
}

修改routes.py:

# 景点按照评分排名
@main.route('/scoreRank', methods=['GET'])
def getScoreRank():try:top_tours = Tour.query.filter(Tour.comments>1000).order_by(Tour.score.desc()).limit(5).all()result = tours_schema.dump(top_tours)return make_response(data=result)except Exception as e:return make_response(code=1, message=str(e))

修改BarChart.vue:

import {getScoreRank} from "@/api/tour";mounted() {getScoreRank().then(res => {// console.log(res.data.data);this.chartOptions.xAxis.data = res.data.data.map(item => item.title);this.chartOptions.series[0].data = res.data.data.map(item => item.score);})}

效果:
在这里插入图片描述

7 饼图的对接

tour.js中添加方法:

// 按照评分排名 
export function getScoreRank() {return request({url:  '/scoreRank',method: 'get'})
}

修改routes.py:

# 由于评分都很近,因此这边限制了评论数超过1000的景点再按照评分来排名
# 这样区分度大,不至于前端的柱状图都是10分
# 景点按照城市统计
@main.route('/cityRank', methods=['GET'])
def getCityRank():try:ret = db.session.query(Tour.city.label('name'),db.func.count(Tour.id).label('value')).group_by(Tour.city).order_by(db.desc('value')).all()result = chart_schema.dump(ret)return make_response(data=result)except Exception as e:return make_response(code=1, message=str(e))

修改schemas.py,用来封装饼图数据的,添加:

class ChartData(ma.Schema):class Meta:fields = ('name', 'value')chart_schema = ChartData(many=True)

修改PieChart.vue:

import {getCityRank} from "@/api/tour";mounted() {getCityRank().then(res => {// console.log(res.data);this.chartOptions.series[0].data = res.data.data})}

效果:

在这里插入图片描述

8 小结

这期完成了对三个echarts图形的前后端对接,后端实现了从数据库获取数据(利用sqlalchemy + pymsyql 方式),并且对返回也是对了封装的,总的来说成果斐然 👍🏻。
三个图都实现了前后端对接:
在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【超音速专利 CN109636858A】锂电池涂布图像采集标定方法、系统、设备及存储介质
  • Pod的调度机制
  • 深入探索 Wireshark——网络封包分析的利器
  • yolov8人脸识别案例
  • 设计模式 - 单例模式
  • 密码学基本理论
  • pnpm -C 什么意思
  • 量化投资策略与技术学习PART2:量化选股之风格轮动
  • Docker深入讲解
  • IOS企业IPA软件证书 苹果签名证书 有效期到2026年
  • VMware ESXi学习笔记
  • 【网络安全学习】SQL注入02:使用sqlmap进行注入
  • WPS宏实现对表格选中区域数据进行遍历读取及动态赋值
  • vs2022 开发vue带后端
  • 代码整洁之道-如何写好注释
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • AHK 中 = 和 == 等比较运算符的用法
  • C++11: atomic 头文件
  • github指令
  • gitlab-ci配置详解(一)
  • Git的一些常用操作
  • HTTP中GET与POST的区别 99%的错误认识
  • iOS编译提示和导航提示
  • java8-模拟hadoop
  • Java精华积累:初学者都应该搞懂的问题
  • Linux下的乱码问题
  • Vue--数据传输
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 从setTimeout-setInterval看JS线程
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • ------- 计算机网络基础
  • 树莓派 - 使用须知
  • 网页视频流m3u8/ts视频下载
  • 译自由幺半群
  • 用 Swift 编写面向协议的视图
  • No resource identifier found for attribute,RxJava之zip操作符
  • 【干货分享】dos命令大全
  • AI算硅基生命吗,为什么?
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • # wps必须要登录激活才能使用吗?
  • #define
  • (14)Hive调优——合并小文件
  • (9)STL算法之逆转旋转
  • (C)一些题4
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (附源码)计算机毕业设计高校学生选课系统
  • (蓝桥杯每日一题)love
  • (一)为什么要选择C++
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转载)从 Java 代码到 Java 堆
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • .mysql secret在哪_MySQL如何使用索引
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)