pyecharts Django

2023-02-17 11:12 更新
本指南介紹了如何在 Django 中使用 pyecharts。

Django 模板渲染

Step 0: 新建一個(gè) Django 項(xiàng)目

$ django-admin startproject pyecharts_django_demo

創(chuàng)建一個(gè)應(yīng)用程序

$ python manage.py startapp demo

在 ?pyecharts_django_demo/settings.py? 中注冊應(yīng)用程序

# pyecharts_django_demo/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'demo'  # <---
]

編輯 ?demo/urls.py? 文件

# demo/urls.py
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
]

在 ?pyecharts_django_demo/urls.py? 中新增 'demo.urls'

pyecharts_django_demo/urls.py
from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'demo/', include('demo.urls'))  # <---
]

Step 1: 拷貝 pyecharts 模板

先在 ?demo ?文件夾下新建 templates 文件夾

chenjiandongx@DESKTOP-E83NUHA:/mnt/d/Python/pyecharts-django-demo/pyecharts_django_demo/demo$ ls
__init__.py  __pycache__  admin.py  apps.py  migrations  models.py  templates  tests.py  urls.py  views.py

將 pyecharts 模板,位于 ?pyecharts.render.templates? 拷貝至剛新建的 templates 文件夾

chenjiandongx@DESKTOP-E83NUHA:/mnt/d/Python/pyecharts-django-demo/pyecharts_django_demo/demo/templates$ tree
.
├── jupyter_lab.html
├── jupyter_notebook.html
├── macro
├── nteract.html
├── simple_chart.html
├── simple_page.html
└── table.html

Step 2: 渲染圖表

將下列代碼保存到 ?demo/views.py? 中。

from jinja2 import Environment, FileSystemLoader
from pyecharts.globals import CurrentConfig
from django.http import HttpResponse

CurrentConfig.GLOBAL_ENV = Environment(loader=FileSystemLoader("./demo/templates"))

from pyecharts import options as opts
from pyecharts.charts import Bar


def index(request):
    c = (
        Bar()
        .add_xaxis(["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"])
        .add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
        .add_yaxis("商家B", [15, 25, 16, 55, 48, 8])
        .set_global_opts(title_opts=opts.TitleOpts(title="Bar-基本示例", subtitle="我是副標(biāo)題"))
    )
    return HttpResponse(c.render_embed())

Step 3: 運(yùn)行項(xiàng)目

$ python manage.py runserver

使用瀏覽器打開 http://127.0.0.1:8000/demo 即可訪問服務(wù)

Django 前后端分離

Step 0: 新建一個(gè) Django 項(xiàng)目

$ django-admin startproject pyecharts_django_demo

創(chuàng)建一個(gè)應(yīng)用程序

$ python manage.py startapp demo

在 ?pyecharts_django_demo/settings.py? 中注冊應(yīng)用程序

# pyecharts_django_demo/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'demo',  # <--- app 名稱
    'rest_framework',
]

在 ?pyecharts_django_demo/urls.py? 中新增 'demo.urls'

from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^demo/', include('demo.urls'))
]

編輯 ?demo/urls.py? 文件(沒有就新建一個(gè))

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^bar/$', views.ChartView.as_view(), name='demo'),
    url(r'^index/$', views.IndexView.as_view(), name='demo'),
]

Step 2 編寫畫圖 HTML 代碼

先在根目錄文件夾下新建 templates 文件夾,新建一個(gè) index.html

sunhailindeMacBook-Pro:pyecharts_django_demo sunhailin$ ls
__pycache__   db.sqlite3   demo   manage.py  pyecharts_django_demo  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" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" ></script>
    <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" ></script>

</head>
<body>
    <div id="bar" style="width:1000px; height:600px;"></div>
    <script>
        var chart = echarts.init(document.getElementById('bar'), 'white', {renderer: 'canvas'});

        $(
            function () {
                fetchData(chart);
            }
        );

        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>

Step 3: 編寫 Django 和 pyecharts 代碼渲染圖表

注: 目前由于 json 數(shù)據(jù)類型的問題,無法將 pyecharts 中的 JSCode 類型的數(shù)據(jù)轉(zhuǎn)換成 json 數(shù)據(jù)格式返回到前端頁面中使用。因此在使用前后端分離的情況下盡量避免使用 JSCode 進(jìn)行畫圖。

將下列代碼保存到 ?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
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 bar_base() -> Bar:
    c = (
        Bar()
        .add_xaxis(["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"])
        .add_yaxis("商家A", [randrange(0, 100) for _ in range(6)])
        .add_yaxis("商家B", [randrange(0, 100) for _ in range(6)])
        .set_global_opts(title_opts=opts.TitleOpts(title="Bar-基本示例", subtitle="我是副標(biāo)題"))
        .dump_options_with_quotes()
    )
    return c


class ChartView(APIView):
    def get(self, request, *args, **kwargs):
        return JsonResponse(json.loads(bar_base()))


class IndexView(APIView):
    def get(self, request, *args, **kwargs):
        return HttpResponse(content=open("./templates/index.html").read())

Step 4: 運(yùn)行項(xiàng)目

$ python manage.py runserver

使用瀏覽器打開 http://127.0.0.1:8000/demo/index 即可訪問服務(wù)

定時(shí)全量更新圖表

前端主動(dòng)向后端進(jìn)行數(shù)據(jù)刷新

定時(shí)刷新的核心在于 html 的 ?setInterval? 方法。

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" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" ></script>
    <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" ></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);
                setInterval(fetchData, 2000);
            }
        );

        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>

定時(shí)增量更新圖表

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" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" ></script>
    <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" ></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, 2000);
            }
        );

        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>

后端代碼也需要相應(yīng)做出改變

編輯 ?demo/urls.py? 文件(沒有就新建一個(gè))

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^line/$', views.ChartView.as_view(), name='demo'),
    url(r'^lineUpdate/$', views.ChartUpdateView.as_view(), name='demo'),
    url(r'^index/$', views.IndexView.as_view(), name='demo'),
]
import json
from random import randrange

from django.http import HttpResponse
from rest_framework.views import APIView

from pyecharts.charts import Line
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 line_base() -> Line:
    line = (
        Line()
        .add_xaxis(list(range(10)))
        .add_yaxis(series_name="", y_axis=[randrange(0, 100) for _ in range(10)])
        .set_global_opts(
            title_opts=opts.TitleOpts(title="動(dòng)態(tài)數(shù)據(jù)"),
            xaxis_opts=opts.AxisOpts(type_="value"),
            yaxis_opts=opts.AxisOpts(type_="value")
        )
        .dump_options_with_quotes()
    )
    return line


class ChartView(APIView):
    def get(self, request, *args, **kwargs):
        return JsonResponse(json.loads(line_base()))


cnt = 9


class ChartUpdateView(APIView):
    def get(self, request, *args, **kwargs):
        global cnt
        cnt = cnt + 1
        return JsonResponse({"name": cnt, "value": randrange(0, 100)})

class IndexView(APIView):
    def get(self, request, *args, **kwargs):
        return HttpResponse(content=open("./templates/index.html").read())


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號