项目代码已托管到github,地址见:https://github.com/ybqdren/BygjRace-DataShowChart

- 一、起步-新建项目

配置环境

1.新建Python项目 命名为01_MyFlaskTest

2.在Teminal中安装pipenv

  1. pip install pipenv

3.创建当前项目空间的虚拟环境

  1. pipenv install

4.激活虚拟环境

  1. pipenv shell

在teminal中执行上述指令,会返现项目路径前出现’(虚拟环境名称)$’类似字段。

这表明Pipenv已经为我们的项目激活了虚拟环境的子shell,此时虚拟环境表示已经激活成功了

安装三方包

1.安装flask

  1. pipenv install flask

2.安装flask-sqlalchemy

  1. pipenv install flask-sqlalchemy

3,安装Jinja2

  1. pipenv install jinja2

4.安装flask-mysqldb(sqlalchemy连接mysql数据库必须)

  1. pipenv install mysqldb

5.安装flask-migrate

  1. pipenv install flask-migrate

6.安装flask-script

  1. pipenv install flask-script

7.安装SQLAlchemy

  1. pipenv install SQLAlchemy

按照目录规范添加目录

如图:
Echarts | 从0开始搭建Flask-Echarts数据可视化项目 - 图1

-二、开始编码

Flask实例对象准备

1.定义flask app实例创建工厂函数

app/init.py

  1. def create_app(app_name):
  2. app = Flask(app_name)
  3. return app

2.在工厂函数中装配db

app/extensions.py

  1. from flask_sqlalchemy import SQLAlchemy
  2. from flask import Flask
  3. #创建对象
  4. db = SQLAlchemy()
  5. #初始化
  6. def config_extensions(app):
  7. db.init_app(app)

app/config.py

  1. import os
  2. class Config():
  3. SQLALCHEMY_DATABASE_URI = 'mysql://root:666666@127.0.0.1:3306/race_flask'
  4. SQLALCHEMY_TRACK_MODIFICATIONS = True
  5. SQLALCHEMY_ECHO = True

app/init.py

  1. def create_app(app_name):
  2. app = Flask(app_name)
  3. app.config.from_object(Config)
  4. config_extensions(app) #装配SQLAlchemy对象 db
  5. return app

蓝图准备

1.创建蓝图实例对象

app/views/main.py

  1. from flask import Blueprint
  2. # 创建蓝图
  3. main_print = Blueprint('main_print',__name__)

2.提供蓝本注册函数

app/veiws/main/init.py

  1. from .main import main_print
  2. # 封装
  3. DEFAULT_BLUEPRINT = {
  4. (main_print,'')
  5. }
  6. #蓝图注册
  7. def config_blueprint(app):
  8. for blueprint,prefix in DEFAULT_BLUEPRINT:
  9. app.register_blueprint(blueprint,prefix=prefix)

前端页面准备

1.echarts文件构建下载

  1. https://echarts.apache.org/zh/builder.html

2.前端显示页面准备

app/templates/main/index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>数据可视化展示页面</title>
  6. <script src="/static/js/echarts.min.js"></script>
  7. </head>
  8. <body>
  9. </body>
  10. </html>

3.蓝图中构建视图函数

app.views.main.py

  1. from flask import render_template
  2. @main_print.route('/index')
  3. def index():
  4. return render_template('/main/index.html')

- 三、数据与模型类

模型类

app/modles/tbl_video_game_sales.py

  1. from app.extensions import db
  2. class Tbl_Video_Game_Sales(db.Model):
  3. __tablename__ = 't_video_game_sales'
  4. Rank = db.Column(db.String(255),primary_key=True) #销售排名
  5. Name = db.Column(db.String(255)) #游戏名称
  6. Platform = db.Column(db.String(255)) #该游戏发布平台
  7. Year = db.Column(db.Integer) #发布年份(1980-2016)
  8. Genre = db.Column(db.String(255)) #游戏类型
  9. Publisher = db.Column(db.String(255)) #出版公司
  10. NA_Sales = db.Column(db.DECIMAL(255,2)) #北美区域销量(以百万为单位计数)
  11. EU_Sales = db.Column(db.DECIMAL(255,2)) #欧美区域销量(以百位为单位计数)
  12. JP_Sales = db.Column(db.DECIMAL(255,2)) #日本区域销量(以百位为单位计数)
  13. Other_Sales = db.Column(db.DECIMAL(255,2)) #其他国家销量(以百位为单位计数)
  14. Global_Sales = db.Column(db.DECIMAL(255,2)) #全球销量(以百位为单位计数)

app/models/init.py

  1. from .tbl_video_game_sales import Tbl_Video_Game_Sales

数据迁移

1.创建迁移仓库

创建数据迁移对象

app/extensions.py

  1. from flask_sqlalchemy import SQLAlchemy
  2. from flask import Flask
  3. from flask_migrate import Migrate,MigrateCommand
  4. #创建对象
  5. db = SQLAlchemy()
  6. migrate = Migrate()
  7. #初始化
  8. def config_extensions(app):
  9. db.init_app(app)
  10. migrate.init_app(app,db)

manager.py

  1. from app import create_app
  2. from app.views import config_blueprint
  3. from flask_script import Manager
  4. from flask_migrate import MigrateCommand
  5. app = create_app('app')
  6. config_blueprint(app)
  7. manager = Manager(app)
  8. manager.add_command('db',MigrateCommand)#使用 MigrateCommand类使用db命令附加
  9. if __name__ == '__main__':
  10. manager.run()

Terminal上输入

  1. python manage.py db init

flask-migrate会为我们生成一个迁移文件夹
Echarts | 从0开始搭建Flask-Echarts数据可视化项目 - 图2

2.创建迁移脚本

  1. python manage.py db migrate

使用migrate子命令可以自动生成迁移脚本
Echarts | 从0开始搭建Flask-Echarts数据可视化项目 - 图3

ORM模型映射

此处参考:https://flask-sqlalchemy.palletsprojects.com/en/2.x/contexts/

当前步骤在Python Console中完成

1.导入工厂函数创建Flask实例对象

  1. from app import create_app
  2. app = create_app('app')

2.设置应用上下文(重要!)

  1. app.app_context().push()

如果此处不推送上下文,会报错:No application found. Either work inside a view function or push an application context.

3.导入实例化的SQLAlchemy对象db,并绑定app

  1. from app.extensions import db
  2. db.init_app(app)

此时查看db对象,就会发现已经成功绑定了flask实例对象,并成功读取到配置信息

Echarts | 从0开始搭建Flask-Echarts数据可视化项目 - 图4

4.导入orm模型类

  1. from app.models import Tbl_Video_Game_Sales

5.执行db.create_all()指令

  1. db.create_all()
  2. db.session.commit()

6.测试orm模型映射是否成功

  1. Tbl_Video_Game_Sales.query.all()[:2]

查询结果
Echarts | 从0开始搭建Flask-Echarts数据可视化项目 - 图5

- 四、数据可视化

建立页面模板 ‘base.html’

app/templates/base.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>{% block head_title%}{% endblock head_title%}</title>
  6. <script src="/static/js/echarts.min.js"></script>
  7. <style>
  8. #main{
  9. width: 1000px;
  10. height: 500px;
  11. margin-left: auto;
  12. margin-right: auto;
  13. margin-top:20px;
  14. }
  15. #content-id{
  16. text-align: center;
  17. font-size: 30px;
  18. padding-top: 20px;
  19. }
  20. </style>
  21. </head>
  22. {% block content%}
  23. {% endblock content%}
  24. </html>

导入模型类

  1. from app.models import Tbl_Video_Game_Sales

开启调试模式

  1. from flask_script import Server
  2. manager.add_command("runserver",Server(use_debugger=True))

1.柱状图

柱形图 -> 同一对象不对维度份额比较

视图函数

  1. @main_print.route('/charts/bar')
  2. def charts_bar():
  3. game_sale = Tbl_Video_Game_Sales.query.first()
  4. return render_template('/main/bar-chart.html',game_sale = game_sale)

页面

  1. {% extends 'base.html'%}
  2. {% block head_title %}
  3. 数据可视化展示-柱状图
  4. {% endblock head_title%}
  5. {% block content %}
  6. <body>
  7. <div id="content-id">柱状图-bar</div>
  8. <div id="main"></div>
  9. <script type="text/javascript">
  10. var barChart = echarts.init(document.getElementById('main'));
  11. var option = {
  12. title: {
  13. text: '{{game_sale.Name}}各区域销量',
  14. subtext: '单位:百万'
  15. },
  16. tooltip:{},
  17. xAxis: {
  18. data: ["北美","欧美","日本","其他国家"]
  19. },
  20. yAxis: {
  21. type:'value'
  22. },
  23. series: [{
  24. name: '销量',
  25. type: 'bar',
  26. data: [{{game_sale.NA_Sales}}, {{game_sale.EU_Sales}}, {{game_sale.jp_Sales}}, {{game_sale.Other_Sales}}]
  27. }]
  28. };
  29. barChart.setOption(option);
  30. </script>
  31. </body>
  32. {% endblock content %}

Echarts | 从0开始搭建Flask-Echarts数据可视化项目 - 图6

2.折线图

数据i变化趋势

视图函数

  1. @main_print.route('/charts/line')
  2. def charts_line():
  3. game = dict()
  4. for y in range(1999,2011,1):
  5. count = Tbl_Video_Game_Sales.query.filter(Tbl_Video_Game_Sales.Year == y).count()
  6. game[y] = count
  7. return render_template('/main/line-chart.html',game = game)

页面

  1. {% extends 'base.html'%}
  2. {% block head_title%}
  3. 数据可视化展示-折线图
  4. {% endblock %}
  5. {% block content %}
  6. <body>
  7. <div id="content-id">折线图-line</div>
  8. <div id="main"></div>
  9. </body>
  10. <script>
  11. var line_chart = echarts.init(document.getElementById('main'));
  12. var option = {
  13. title:{
  14. text:'2000年~2010年发行游戏数量增长趋势',
  15. subtext:'单位:个'
  16. },
  17. tooltip:{},
  18. xAxis:{
  19. type:'category',
  20. data:[{%for g in game%}'{{ g }}',{% endfor %}]
  21. },
  22. yAxis:{},
  23. series:[{
  24. type:'line',
  25. data:[{% for g in game%}{{game[g]}},{% endfor %}]
  26. }]
  27. };
  28. line_chart.setOption(option);
  29. </script>
  30. {% endblock %}

Echarts | 从0开始搭建Flask-Echarts数据可视化项目 - 图7

3.双图表切换(折线/柱)

视图函数

  1. @main_print.route('/charts/changeView')
  2. def change_View():
  3. game_sale = Tbl_Video_Game_Sales.query.order_by(Tbl_Video_Game_Sales.Global_Sales.desc()).first()
  4. return render_template('/main/changeView-chart.html',game_sale = game_sale)

页面

  1. {% extends 'base.html' %}
  2. {% block head_title%}
  3. 图像切换-折线图/柱状图
  4. {% endblock head_title%}
  5. {% block content %}
  6. <body>
  7. <div id="content-id">折线图/柱形图-line/bar</div>
  8. <div id="main"></div>
  9. </body>
  10. <script>
  11. my_chart = echarts.init(document.getElementById('main'));
  12. var option = {
  13. title:{
  14. text:'一个简单的折/柱切换图',
  15. },
  16. tooltip:{
  17. trigger:'item'
  18. },
  19. toolbox:{
  20. feature:{
  21. magicType:{
  22. type:['line','bar']
  23. }
  24. }
  25. },
  26. xAxis:{
  27. type:'category',
  28. data:["北美","欧美","日本","其他国家"]
  29. },
  30. yAxis: {},
  31. series:[{
  32. type:'line',
  33. data: [{{game_sale.NA_Sales}}, {{game_sale.EU_Sales}}, {{game_sale.jp_Sales|default('3.5')}}, {{game_sale.Other_Sales}}]
  34. }]
  35. };
  36. my_chart.setOption(option);
  37. </script>
  38. {% endblock content %}

Echarts | 从0开始搭建Flask-Echarts数据可视化项目 - 图8

4.雷达图

多维度数据展示

视图函数

  1. @main_print.route('/charts/radar')
  2. def charts_radar():
  3. game = Tbl_Video_Game_Sales.query.filter(Tbl_Video_Game_Sales.Platform == 'Wii').all()[:3]
  4. return render_template('/main/radar-chart.html',game = game)

页面

  1. {% extends 'base.html'%}
  2. {% block head_title %}
  3. 数据可视化展示-雷达图
  4. {% endblock head_title %}
  5. {% block content %}
  6. <body>
  7. <div id="content-id">雷达图-radar</div>
  8. <div id="main"></div>
  9. <script>
  10. var na_sales = [{% for g in game%}{{ g.NA_Sales }},{% endfor %}]; //北美地区销量
  11. var eu_sales = [{% for g in game %}{{ g.EU_Sales }},{% endfor %}]; //欧美地区销量
  12. var jp_sales = [{% for g in game %}{{ g.JP_Sales }},{% endfor %}]; //日本地区销量
  13. var other_sales = [{% for g in game%}{{ g.Other_Sales }},{% endfor %}]; //其他地区销量
  14. var radar_chart = echarts.init(document.getElementById('main'));
  15. var option = {
  16. title:{
  17. text:'各区域销量'
  18. },
  19. tooltip:{},
  20. legend:{
  21. data:[{% for g in game %}'{{ g.Name }}',{% endfor %}],
  22. },
  23. radar:{
  24. indicator:[
  25. {name:'北美',max:50},
  26. {name:'欧洲',max:50},
  27. {name:'日本',max:50},
  28. {name:'其他',max:50}
  29. ]
  30. },
  31. series: [{
  32. type:'radar',
  33. data:[
  34. {% for g in game%}
  35. {
  36. value:[na_sales[{{ loop.index }}-1],eu_sales[{{ loop.index }}-1],jp_sales[{{ loop.index }}-1],other_sales[{{ loop.index }}-1]],
  37. name:'{{ g.Name }}'
  38. },
  39. {% endfor %}
  40. ]
  41. }]
  42. };
  43. radar_chart.setOption(option);
  44. </script>
  45. </body>
  46. {% endblock content %}

Echarts | 从0开始搭建Flask-Echarts数据可视化项目 - 图9

5.饼图

同一对象组成展示

视图函数

  1. @main_print.route('/charts/pie')
  2. def charts_pie():
  3. game = Tbl_Video_Game_Sales.query.filter(Tbl_Video_Game_Sales.Platform == 'PS3').order_by(Tbl_Video_Game_Sales.Global_Sales.desc()).all()[:10]
  4. return render_template('/main/pie-chart.html',game = game)

页面

  1. {% extends 'base.html' %}
  2. {% block head_title%}
  3. 数据可视化展示-饼图
  4. {% endblock head_title%}
  5. {% block content %}
  6. <body>
  7. <div id="content-id">饼图-pie</div>
  8. <div id="main"></div>
  9. <script>
  10. var na_sales = [{% for g in game %}{{ g.NA_Sales}},{% endfor %}];
  11. var eu_sales = [{% for g in game %}{{g.EU_Sales}},{% endfor %}];
  12. var jp_sales = [{% for g in game %}{{g.JP_Sales}},{% endfor %}];
  13. var other_sales = [{% for g in game %}{{g.Other_Sales}},{% endfor %}];
  14. var avg_na =eval( na_sales.join("+"));
  15. var avg_eu = eval(eu_sales.join("+"));
  16. var avg_jp = eval(jp_sales.join("+"));
  17. var avg_other = eval(other_sales.join("+"));
  18. var pie_chart = echarts.init(document.getElementById('main'));
  19. var option = {
  20. title:{
  21. text:'PS3平台游戏销量区域份额',
  22. subtext:'摘取销量前十游戏数据'
  23. },
  24. tooltip:{
  25. formatter:'【{b}区域销量】 <br/> {c}百万份({d}%)'
  26. },
  27. legend:{
  28. data:['北欧','欧洲','日本','其他']
  29. },
  30. series:[
  31. {
  32. type:'pie',
  33. radius:['25%','50%'],
  34. data:[
  35. {value:avg_na,name:'北欧'},
  36. {value:avg_eu,name:'欧洲'},
  37. {value:avg_jp,name:'日本'},
  38. {value:avg_other,name:'其他'}
  39. ]
  40. }
  41. ]
  42. };
  43. pie_chart.setOption(option);
  44. </script>
  45. </body>
  46. {% endblock content %}

Echarts | 从0开始搭建Flask-Echarts数据可视化项目 - 图10

6.南丁格尔图(玫瑰图)

比饼图更直观

视图函数

  1. @main_print.route('/charts/rosePie')
  2. def charts_rosePie():
  3. game = Tbl_Video_Game_Sales.query.filter(Tbl_Video_Game_Sales.Platform == 'PS3').order_by(Tbl_Video_Game_Sales.Global_Sales.desc()).all()[:10]
  4. return render_template('/main/rosePie-chart.html',game = game)

页面

  1. {% extends 'base.html' %}
  2. {% block head_title%}
  3. 数据可视化展示-南丁格尔图
  4. {% endblock head_title%}
  5. {% block content %}
  6. <body>
  7. <div id="content-id">南丁格尔图-rosePie</div>
  8. <div id="main"></div>
  9. <script>
  10. var na_sales = [{% for g in game %}{{ g.NA_Sales}},{% endfor %}];
  11. var eu_sales = [{% for g in game %}{{g.EU_Sales}},{% endfor %}];
  12. var jp_sales = [{% for g in game %}{{g.JP_Sales}},{% endfor %}];
  13. var other_sales = [{% for g in game %}{{g.Other_Sales}},{% endfor %}];
  14. var avg_na =eval( na_sales.join("+"));
  15. var avg_eu = eval(eu_sales.join("+"));
  16. var avg_jp = eval(jp_sales.join("+"));
  17. var avg_other = eval(other_sales.join("+"));
  18. var pie_chart = echarts.init(document.getElementById('main'));
  19. var option = {
  20. title:{
  21. text:'PS3平台游戏销量区域份额',
  22. subtext:'摘取销量前十游戏数据'
  23. },
  24. tooltip:{
  25. formatter:'【{b}区域销量】 <br/> {c}百万份({d}%)'
  26. },
  27. legend:{
  28. data:['北欧','欧洲','日本','其他']
  29. },
  30. series:[
  31. {
  32. type:'pie',
  33. radius:['25%','50%'],
  34. data:[
  35. {value:avg_na,name:'北欧'},
  36. {value:avg_eu,name:'欧洲'},
  37. {value:avg_jp,name:'日本'},
  38. {value:avg_other,name:'其他'}
  39. ],
  40. roseType:'radius' //area
  41. }
  42. ]
  43. };
  44. pie_chart.setOption(option);
  45. </script>
  46. </body>
  47. {% endblock content %}

Echarts | 从0开始搭建Flask-Echarts数据可视化项目 - 图11

- 项目启动

  1. python manage.py runserver