在渲染的模板中绘制类属性

时间:2019-08-07 11:39:40

标签: python class flask plot

我有一个简单的课:

class Simple():
    def __init__(self, x, y):
        self.x = x
        self.y = y

我绕过一个flask.Flask实例

import flask

s = Simple(x=[1,2,3,4,5], y=[1,4,9,16,25])

app = flask.Flask(__name__)

@app.route('/')
def index():
    return flask.render_template('index.html', simple=s)

index.html模板如下所示:

<!DOCTYPE html>
<html lang="en-US">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
    <title>Simple Class</title>
</head>

<body>
    <h2>{{ simple.x, simple.y }}</h2>

    <canvas id="bar-chart" width="800" height="450"></canvas>
    <script type="text/javascript">
        new Chart(document.getElementById("bar-chart"), {
            type: 'bar',
            data: {
              labels: **simple.x(?)**,
              datasets: [
                {
                  data: **simple.y(?)**
                }
              ]
            },
            options: {
              legend: { display: false },
              title: {
                display: false,
              }
            }
        });
    </script>


</body>

</html>

请问如何绘制x实例的ysimple属性?

1 个答案:

答案 0 :(得分:0)

这是一个包含许多解决方案的令人难以置信的广泛问题。您可以执行以下任一操作:

  1. 在服务器端使用Python创建图像文件,并将其发送到前端以供浏览器呈现。

  2. 使用具有javascript绑定的Python库之一(例如Bokeh或Plotly)通过程序包API创建绘图并在浏览器中呈现。

  3. 将数据作为json服务,并使用诸如Charts.js之类的javascript库将绘图完全呈现在前端。


要完成第一项,可以使用matplotlib创建数据图,将图保存到BytesIO文件对象中,渲染时从对象中读取字节作为模板的一部分。您将需要创建其他路由来做到这一点。

from matplotlib import pyplot as plt
from flask import send_file
from io import BytesIO
import json

# turn off interactive plotting
plt.ioff()

def make_xyplot(x, y):
    fig, ax = plt.subplots(1, 1, figsize=(4,4))
    ax.scatter(x, y) # or ax.plot or ax.bar or etc...

    # create the binary file object, write to it, set the cursor to the beginning 
    f_obj = BytesIO()
    fig.savefig(f_obj, format='png')
    f_obj.seek(0)
    return f_obj

@route('/xyplot/<x>/<y>', methods='GET')
def xyplot(x, y):
    x = json.loads(x)
    y = json.loads(y)
    return send_file(make_xyplot(x, y), attachment_filename='xyplot.png', mimetype='image/png')

为了确保使用get方法时不会发生任何奇怪的事情,我们可以向简单对象添加json属性,并将其用于get请求。

class Simple():
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @property
    def jx(self):
        return json.dumps(self.x, separators=(',',';'))

    @property
    def jy(self):
        return json.dumps(self.y, separators=(',',';'))

simple = Simple([1, 2, 3, 4, 5], [2, 3, 2, 4, 3])
simple.x
# returns
[1, 2, 3, 4, 5]

simple.jx
# returns
'[1,2,3,4,5]'  # no spaces

您可以从此处将图像作为静态文件加载到模板中。

<!DOCTYPE html>
<html lang="en-US">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Simple Class</title>
</head>

<body>
    <h2>{{ simple.x, simple.y }}</h2>
    <img src="/xyplot/{{ simple.jx }}/{{ simple.jy }}">
</body>

</html>