【问题标题】:How to embed matplotlib graph in Django webpage?如何在 Django 网页中嵌入 matplotlib 图?
【发布时间】:2016-11-10 18:35:26
【问题描述】:

所以,请多多包涵,因为我对 Django、Python 和一般的 Web 开发还很陌生。我想要做的是显示我使用 matplotlib 制作的图表。我让它工作到主页自动重定向到图形的 png(基本上是浏览器中显示图形的选项卡)。但是,现在我想要的是查看带有简单嵌入图形的实际主页。换句话说,我想看到导航栏等,然后是网站正文中的图表。

到目前为止,我已经进行了搜索,并且对如何完成此任务有所了解。我在想的是有一个简单地返回图表的特殊视图。然后,以某种方式从我的模板中的 img src 标签访问这个 png 图像,我将使用它来显示我的数据。

图形代码:

from django.shortcuts import render
import urllib
import json
from django.http import HttpResponse
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
import datetime as dt
import pdb

def index(request):
    stock_price_url = 'https://www.quandl.com/api/v3/datatables/WIKI/PRICES.json?ticker=GOOGL&date.gte=20151101&qopts.columns=date,close&api_key=KEY'

    date = []
    price = []

    #pdb.set_trace()
    source_code = urllib.request.urlopen(stock_price_url).read().decode()

    json_root = json.loads(source_code)
    json_datatable = json_root["datatable"]
    json_data = json_datatable["data"]

    for day in json_data:
        date.append(dt.datetime.strptime(day[0], '%Y-%m-%d'))
        price.append(day[1])

    fig=Figure()
    ax = fig.add_subplot(1,1,1)

    ax.plot(date, price, '-')

    ax.set_xlabel('Date')
    ax.set_ylabel('Price')
    ax.set_title("Google Stock")

    canvas = FigureCanvas(fig)
    response = HttpResponse(content_type='image/png')
    #canvas.print_png(response)
    return response

模板代码:

{% extends "home/header.html" %}
  {% block content %}
  <p>Search a stock to begin!</p>
  <img src="home/graph.py" />

  {% endblock %}

我现在得到了什么:

Current Page

【问题讨论】:

  • 找到我的问题的答案here.
  • 您能否详细说明我可以在您给定的链接中找到解决方案的位置?谢谢:)
  • @sphoenix 我已经有一段时间没有和 Django 合作了,但我相信是这个here

标签: python django matplotlib graph


【解决方案1】:

我知道这个问题被标记为 matplotlib,但我需要做同样的事情,我发现 plotly 更易于使用且视觉上也很吸引人。您可以简单地绘制一个图形,然后在视图中获取图形的 html 代码:

# fig is plotly figure object and graph_div the html code for displaying the graph
graph_div = plotly.offline.plot(fig, auto_open = False, output_type="div")
# pass the div to the template

在模板中做:

<div style="width:1000;height:100">
{{ graph_div|safe }}
</div>

【讨论】:

    【解决方案2】:

    我搜索了很多,直到找到了一个在 Django 页面上渲染 matplotlib 图像时对我有用的解决方案。通常,只是打印一个冗长的字符串,而不是生成可视化。所以,最终对我有用的是以下内容:

    首先,导入:

    import matplotlib.pyplot as plt
    from io import StringIO
    import numpy as np
    

    虚拟函数返回图形如下:

    def return_graph():
    
        x = np.arange(0,np.pi*3,.1)
        y = np.sin(x)
    
        fig = plt.figure()
        plt.plot(x,y)
    
        imgdata = StringIO()
        fig.savefig(imgdata, format='svg')
        imgdata.seek(0)
    
        data = imgdata.getvalue()
        return data
    

    这个可以被其他函数调用,使用和渲染return_graph()返回的图像:

    def home(request):
        context['graph'] = return_graph()
        return render(request, 'x/dashboard.html', context)
    

    而在dashboard.html文件中,图形是通过以下命令嵌入的:

    {{ graph|safe }}
    

    【讨论】:

      【解决方案3】:

      我认为你应该取消注释这一行:

      #canvas.print_png(response)
      

      您可以使用 django HttpResponse 轻松返回绘图,而不是使用一些额外的库。在 matplotlib 中有一个 FigureCanvasAgg 可以让您访问绘制绘图的画布。最后,您可以简单地将其作为 HttpResonse 返回。这里有非常基本的示例。

      import matplotlib.pyplot as plt
      import numpy as np
      from matplotlib.backends.backend_agg import FigureCanvasAgg
      from django.http import HttpResponse
      
      def plot(request):
          # Data for plotting
          t = np.arange(0.0, 2.0, 0.01)
          s = 1 + np.sin(2 * np.pi * t)
      
          fig, ax = plt.subplots()
          ax.plot(t, s)
      
          ax.set(xlabel='time (s)', ylabel='voltage (mV)',
                 title='About as simple as it gets, folks')
          ax.grid()
      
          response = HttpResponse(content_type = 'image/png')
          canvas = FigureCanvasAgg(fig)
          canvas.print_png(response)
          return response
      

      【讨论】:

      • 这是一个简单易懂的响应。我正在尝试与 OP 做同样的事情。我的观点指向一个模板,该模板做了一些事情来显示模型中的数据,但我想知道如何将其合并到该视图中?最后我返回return:“render(request,'viewer.html',context),其中context是我传递给模板的模型中的对象[context = {'modelObj':modelObj,'displayFields':form }]。除了我已经发送的上下文之外,我怎么能像上面一样发送图表?提前谢谢你
      • 请注意,上面的示例可能会导致以下错误:“ValueError: fname must be a PathLike or file handle”。这个问题解决了发生这种情况的一些原因:stackoverflow.com/questions/49542459/…
      【解决方案4】:

      我的设置:

      Django==2.2.2
      windrose==1.6.8
      

      我只是分享我在网上找到的解决方案。我使它与 windrose 和 django 一起工作(感谢一些文章作者)。还有这个

      import base64
      import io
      from matplotlib import pyplot as plt
      
      flike = io.BytesIO()
      plt.savefig(flike)
      b64 = base64.b64encode(flike.getvalue()).decode()
      return render(request, template_name='details_wind.html', context={'wind_rose': wind_rose_image})
      

      在模板中,显示为图片:

      <img src='data:image/png;base64,{{ wind_rose }}'>
      

      【讨论】:

        【解决方案5】:

        如果您想将 matplotlib 图形嵌入到 django-admin 中,您可以尝试 django-matplotlib 字段。此字段不会在数据库中创建列,而是呈现为常规字段。您不需要自定义/子类admin.ModelAdmin,只需在模型中使用此字段并定义如何生成图形。

        【讨论】:

          猜你喜欢
          • 2014-05-09
          • 1970-01-01
          • 1970-01-01
          • 2013-08-05
          • 2011-11-17
          • 1970-01-01
          • 2023-03-24
          • 2012-02-27
          • 2016-05-29
          相关资源
          最近更新 更多