注意:
以下示例是pyecharts官网django示例中的例子,目前发现一处bug,示例3中的定时增量无法实现,我在下面代码中已经改好。
该动态展示的index.html模板中用的还是echarts渲染的,view.py视图下使用pyecharts生成json。index.html中的JavaScript去请求json数据,请求响应结果为success后通过setOption进行解析data字段下的数据绘制图表。
前置条件:
(1)python安装完成
(2)Django安装完成
(3)pyecharts安装完成
pip install pyecharts
(4)APIView安装完成
pip install APIView
1. 新建一个 Django 项目
命令行中输入以下命令
django-admin startproject pyecharts_django_demo
创建一个应用程序
python manage.py startapp demo
效果如下:
创建完之后,在 Pycharm 中打开该项目,当然你也可以直接在 Pycharm 中创建
同时在pyecharts_django_demo/settings.py
中注册应用程序INSTALLED_APPS
中添加应用程序demo
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'demo',
]
在pyecharts_django_demo/urls.py
中新增demo.urls
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('demo/', include('demo.urls')),
]
2. 新建项目 urls 文件
新建demo/urls.py
文件
from django.urls import path
from . import views
urlpatterns = [
path('pie/', views.ChartView.as_view(), name='demoChart'),
path('index/', views.IndexView.as_view(), name='demoIndex'),
]
3. 编写 Django 和 pyecharts 代码渲染图表
由于 json 数据类型的问题,无法将 pyecharts 中的 JSCode 类型的数据转换成 json 数据格式返回到前端页面中使用。
因此在使用前后端分离的情况下尽量避免使用 JSCode 进行画图。
将下列代码保存到demo/views.py
中
import json
from random import randrange
from django.http import HttpResponse
from rest_framework.views import APIView
from pyecharts.charts import Bar, Pie
from pyecharts.faker import Faker
from pyecharts import options as opts
# Create your views here.
def response_as_json(data):
json_str = json.dumps(data)
response = HttpResponse(
json_str,
content_type="application/json",
)
response["Access-Control-Allow-Origin"] = "*"
return response
def json_response(data, code=200):
data = {
"code": code,
"msg": "success",
"data": data,
}
return response_as_json(data)
def json_error(error_string="error", code=500, **kwargs):
data = {
"code": code,
"msg": error_string,
"data": {}
}
data.update(kwargs)
return response_as_json(data)
JsonResponse = json_response
JsonError = json_error
def pie_base() -> Pie:
c = (
Pie()
.add("", [list(z) for z in zip(Faker.choose(), Faker.values())])
.set_colors(["blue", "green", "yellow", "red", "pink", "orange", "purple"])
.set_global_opts(title_opts=opts.TitleOpts(title="Pie-示例"))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
.dump_options_with_quotes()
)
return c
class ChartView(APIView):
def get(self, request, *args, **kwargs):
return JsonResponse(json.loads(pie_base()))
class IndexView(APIView):
def get(self, request, *args, **kwargs):
return HttpResponse(content=open("./templates/index.html").read())
在根目录下新建一个templates
的文件夹,并在该文件夹下新建一个index.html
文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Awesome-pyecharts</title>
<script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
<script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
</head>
<body>
<div id="pie" style="width:1000px; height:600px;"></div>
<script>
var chart = echarts.init(document.getElementById('pie'), 'white', {renderer: 'canvas'});
$(
function () {
fetchData(chart);
}
);
function fetchData() {
$.ajax({
type: "GET",
url: "http://127.0.0.1:8000/demo/pie",
dataType: 'json',
success: function (result) {
chart.setOption(result.data);
}
});
}
</script>
</body>
</html>
python manage.py runserver 127.0.0.1:8000 命令运行
发现报错 sqlite3.OperationalError: no such table: django_session
由于是第一次使用Django的session,所以必须要做以下的操作:
(1)进入cmd,通过cd命令进入到项目根目录下,即manage.py文件所在的文件夹。
(2)执行下面的命令:python manage.py migrate
把相关需要的给配置应用进去了,最后一个就是初始化Django的session,后面跑项目就没问题了。
再次运行,在浏览器中打开http://127.0.0.1:8000/demo/index/,效果如下:
4. 定时全量更新图表
前面讲的是一个静态数据的展示的方法,用 Pyecharts 和 Django 结合最主要是实现一种动态更新数据,增量更新数据等功能。
定时全量更新主要是前端主动向后端进行数据刷新,定时刷新的核心在于 HTML 的 setInterval 方法。
新增index2.html
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Awesome-pyecharts</title>
<script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
<script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
</head>
<body>
<div id="bar" style="width:1600px; height:800px;"></div>
<script>
var chart = echarts.init(document.getElementById('bar'), 'white', {renderer: 'canvas'});
$(
function () {
fetchData(chart);
<!-- refresh time 1000ms-->
setInterval(fetchData, 1000);
}
);
function fetchData() {
$.ajax({
type: "GET",
url: "http://127.0.0.1:8000/demo/bar",
dataType: 'json',
success: function (result) {
chart.setOption(result.data);
}
});
}
</script>
</body>
</html>
同时在demo/views.py
中,增加如下代码:
def bar_base() -> Bar:
c = (
Bar()
.add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
.add_yaxis("商家A", [randrange(20, 100) for _ in range(6)])
.add_yaxis("商家B", [randrange(20, 100) for _ in range(6)])
.set_global_opts(title_opts=opts.TitleOpts(title="Bar-基本示例", subtitle="这是副标题"))
.dump_options_with_quotes()
)
return c
class ChartView2(APIView):
def get(self, request, *args, **kwargs):
return JsonResponse(json.loads(bar_base()))
class IndexView2(APIView):
def get(self, request, *args, **kwargs):
return HttpResponse(content=open("./templates/index2.html").read())
demo/urls.py
中,修改成如下代码:
from django.urls import path
from django.template.defaulttags import url
from . import views
urlpatterns = [
path('pie/', views.ChartView.as_view(), name='demoChart'),
path('index/', views.IndexView.as_view(), name='demoIndex'),
path('bar/', views.ChartView2.as_view(), name='demoChart'),
path('index2/', views.IndexView2.as_view(), name='demoIndex'),
]
运行之后,http://127.0.0.1:8000/demo/index2/效果如下:
Awesome-pyecharts
5. 定时增量更新图表
原理一样,新增index3.html ,代码如下(网上别的教程里这块代码有问题达不到增量更新的效果,我已经做了修改):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Awesome-pyecharts</title>
<script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
<script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
</head>
<body>
<div id="bar" style="width:1600px; height:800px;"></div>
<script>
var chart = echarts.init(document.getElementById('bar'), 'white', {renderer: 'canvas'});
var old_data = [];
$(
function () {
fetchData(chart);
setInterval(getDynamicData, 100);
}
);
function fetchData() {
$.ajax({
type: "GET",
url: "http://127.0.0.1:8000/demo/line",
dataType: "json",
success: function (result) {
var options = result.data;
chart.setOption(options);
old_data = chart.getOption().series[0].data;
}
});
}
function getDynamicData() {
$.ajax({
type: "GET",
url: "http://127.0.0.1:8000/demo/lineUpdate",
dataType: 'json',
success: function (result) {
var options = result.data;
old_data.push([options.name, options.value]);
chart.setOption({
series: [{
data: old_data
}]
});
}
});
}
</script>
</body>
</html>
index3.html中新增了两个请求地址demo/line
,demo/lineUpdate
所以在demo/urls.py
中增加以下路径的匹配(网上别的教程里这块代码有问题达不到增量更新的效果,我已经做了修改):
from django.urls import path
from django.template.defaulttags import url
from . import views
urlpatterns = [
path('pie/', views.ChartView.as_view(), name='demoChart'),
path('index/', views.IndexView.as_view(), name='demoIndex'),
path('bar/', views.ChartView2.as_view(), name='demoChart2'),
path('index2/', views.IndexView2.as_view(), name='demoIndex2'),
path('line/', views.ChartLineView.as_view(), name='demoLine'),
path('lineUpdate/', views.ChartLineUpdateView.as_view(), name='demoLineUpdate'),
path('index3/', views.IndexView3.as_view(), name='demoIndex3'),
]
最后在views.py
中导入Line:
from pyecharts.charts import Bar, Pie, Line
并在views.py
中增加以下代码(网上别的教程里这块代码有问题达不到增量更新的效果,我已经做了修改):
cnt = 0
def line_base() -> Line:
line = (
Line()
.add_xaxis(["{}".format(i) for i in range(10)])
.add_yaxis(
series_name="",
# randrange(xx, xx) for x in range(x) 获取一个二维列表,列表长度为10,值的范围为在区间(50, 80)
# [["0", 63], ["1", 79], ["2", 50], ["3", 65], ["4", 63], ["5", 72], ["6", 69], ["7", 65], ["8", 69], ["9", 64]]
y_axis=[randrange(50, 80) for _ in range(10)],
is_smooth=True,
label_opts=opts.LabelOpts(is_show=False),
)
.set_global_opts(
title_opts=opts.TitleOpts(title="动态数据"),
xaxis_opts=opts.AxisOpts(type_="value"),
yaxis_opts=opts.AxisOpts(type_="value"),
)
.dump_options_with_quotes()
)
return line
class ChartLineView(APIView):
def get(self, request, *args, **kwargs):
return JsonResponse(json.loads(line_base()))
class ChartLineUpdateView(APIView):
def get(self, request, *args, **kwargs):
global cnt
cnt = cnt + 1 # line_base()已经绘制了第0~9个点,接下来从第10个点开始绘制
return JsonResponse({"name": cnt, "value": randrange(50, 80)})
class IndexView3(APIView):
def get(self, request, *args, **kwargs):
global cnt
cnt = 9 # line_base()已经绘制了第0~9个点,接下来从第10个点开始绘制
return HttpResponse(content=open("./templates/index3.html").read())
这样修改后,刷新index3.html会重新画折线图
运行之后,http://127.0.0.1:8000/demo/index3/效果如下:
Awesome-pyecharts
6. 本地加载js文件
另外,如果调试的时候觉得加载 https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js 和 https://assets.pyecharts.org/assets/echarts.min.js 速度太慢可以将这两个js文件保存在本地。
保存在pyecharts_django_demo项目根目录下的/static/js/目录下。
找到setting.py修改STATIC_URL:(输入到该文件的末尾即可,注意符号)
STATIC_URL = '/static/'
STATICFILES_DIRS = ( os.path.join('static'), )
STATIC_ROOT = ''
修改index.html index2.html index3.html文件以下部分即可:
<!-- <script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>-->
<!-- <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>-->
<script src="/static/js/jquery.min.js"></script>
<script type="text/javascript" src="/static/js/echarts.min.js"></script>
7. 修改pyecharts自带的主题
pyechart给使用用户提供了一套主题样式,使用户对其的使用更加方便。
试了下在views.py
中以
Pie(init_opts=opts.InitOpts(theme=ThemeType.DARK))
方式更换主题未生效, 然后发现在index.html下已经设置了“white”主题。
var chart = echarts.init(document.getElementById('pie'), 'white', {renderer: 'canvas'});
将“white”字段修改为“dark”后能生效:
var chart = echarts.init(document.getElementById('pie'), 'dark', {renderer: 'canvas'});
但是这种方式我尝试了一下只有
BUILTIN_THEMES = ["light", "dark", "white"]
中的三种主题会生效。其余的十几种主题无法生效。
--------------------------------------------更新--------------------------------------------
通过html执行的是echarts,所以只能使用默认的三种内置主题。如果需要使用另外的十几种主题可以直接下载主题js文件,在HTML中引入js文件。
主题编辑器网址 >> 主题编辑器 - Apache ECharts
该编辑器中默认的十几种就是pyecharts的globals.py中预设的,并且还能在编辑器中进行修改后再下载js文件。
例如下载了一款名为 wonderland 的主题,将wonderland.js文件放在pyecharts_django_demo项目根目录下的/static/js/theme目录下:
修改index.html index2.html index3.html文件,在<head /><head>中增加以下代码引用js文件:
<script src="/static/js/theme/wonderland.js"></script>
设置“wonderland”主题,保存后刷新页面可以看到主题生效:
var chart = echarts.init(document.getElementById('bar'), 'wonderland', {renderer: 'canvas'});