Django动态展示Pyecharts图表数据

注意:

以下示例是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'});

  • 7
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值