Django:如何将每个图形放在页面上而不保存它

Posted

技术标签:

【中文标题】Django:如何将每个图形放在页面上而不保存它【英文标题】:Django: How to put each graphs on a page without saving it 【发布时间】:2020-03-06 09:59:47 【问题描述】:

我正在努力将使用 Matplotlib 创建的几个图表放在一个页面上,并将其保存在内存中。虽然单个图成功了,但还有一个图失败了。例如,当我尝试在网页中嵌入两个 matplotlib 图(graph1 和 graph2)时,它会显示一个组合图。此外,指定的颜色也不起作用。为什么?我想知道的是如何在没有集成的情况下显示每个图表。

以下是我的代码 Views.py Matplotlib 图被转换为二进制数据并保存在内存中 每个图都连接到url参数

def graph():
#create graph and save it on memory
buff=io.BytesIO()
plt.savefig(buff, format='png')
bute_file=buff.getvalue()
buff.close
return bute_file


def test_graph(request,para):

if para==1: #graph1
    accounts=[6,2,3,6]
    label=['A','B','C','D']
    col=['darkred','red','orange','gold']
    plt.pie(accounts,labels=label,colors=col)
    chart=graph()
    plt.cla
    response=HttpResponse(chart, content_type='image/png')
    return response

elif para==2: #graph2
    accounts=[3,6,9]
    label=['E','F','G']
    col=['blue','cyan','darkblue']
    plt.pie(accounts,labels=label,colors=col)
    chart=graph()
    plt.cla
    response=HttpResponse(chart, content_type='image/png')
    return response

else: #graph3
    accounts=[5,1,2]
    label=['X','Y','Z']
    col=['green','limegreen','yellowgreen']
    plt.pie(accounts,labels=label)
    chart=graph()
    plt.cla
    response=HttpResponse(chart, content_type='image/png')
    return response

url.py

urlpatterns = [
path('test_view/',views.test_view, name='test_view'),
path('test/<int:para>',views.test_graph,name='test_graph')
]

html

 <div>
       <img src="% url 'mysite:test_graph' 1 %">
 </div>

 <div>
      <img src="% url 'mysite:test_graph' 2 %">
 </div>

这是显示的页面

将 test_graph() 中的 para 更改为 url 参数上不存在的 3,4,网页显示了异常的 graph(graph3),似乎运行良好

请给我一些建议或解决方案

PS。以下消息是否涉及? 警告:NSWindow 拖动区域应该只在主线程上无效!这样以后会抛出异常


编辑 我可以通过添加“matplotlib.use('Agg')”来解决 WARING 消息

修改 test_graph 函数 IAW ger.s.brett 建议并消除图函数

def test_graph(request,para):
plt.clf()

if para==1: #graph1
    ..........

elif para==2: #graph2
    ..........

else: #graph3
     .........        

plt.pie(accounts,labels=label,colors=col)
buff=io.BytesIO()
plt.savefig(buff, format='png')
chart=buff.getvalue()
buff.close()

response=HttpResponse(chart, content_type='image/png')
return response

编辑 2 添加输出图,每次访问网页


我得到了答案,以下是修改后的代码

view.py

class TestView(TemplateView):
template_name='mysite/test.html'

def test_graph(self,accounts,label,col):
    plt.pie(accounts,labels=label,colors=col)
    buff=io.BytesIO()
    plt.savefig(buff, format='png')
    buff.seek(0)
    chart=b64encode(buff.getvalue()).decode('utf-8').replace("","")
    plt.close()
    buff.close()
    return chart

def get_context_data(self,**kwargs):
    context=super().get_context_data(**kwargs)

    graph_1=self.test_graph([3,6,9],['E','F','G'],['blue','cyan','darkblue'])
    graph_2=self.test_graph([6,2,3,6],['A','B','C','D'],['darkred','red','orange','gold'])
    context['graph_1']=graph_1
    context['graph_2']=graph_2
    return context

test.html

<div>
     <img src="data:image/png;base64,graph_1">
</div>
<div>
     <img src="data:image/png;base64,graph_2">
</div>

所以...原来如此简单

【问题讨论】:

尝试清除 test_graph 函数开头的 plt:plt.clf()。 感谢 ger.s.brett,我尝试添加 plt.clf()。但这根本解决不了我的问题。更重要的是,每个图形的图形都不一样,每次都重复访问test_graph,例如只显示一个图形,两个相同的graph2s或不显示颜色图形。那么,您有什么建议吗? 我会担心您对 plt 对象的处理。为什么不将其作为函数参数传递给图形函数? 我修改了 test_graph 函数并消除了 graph 函数,这可能会涵盖您指出的内容。尽管如此,这仍然没有解决我的麻烦。我该怎么办......我真的很茫然 现在会发生什么?两次相同的图表? 【参考方案1】:

如果你想在 django 中使用 matplotlib,请使用 django-matplotlib 之类的东西。

只有在使用 python 交互时才使用 plt 对象是一个好主意。

【讨论】:

感谢您给我额外的建议。我尝试将 django_matplotblib 模块集成到我的模型中,将图表嵌入到我的网页中。但它不起作用,而图形可以显示在管理页面上。这是因为无法从模型(DjangoMatplotlibField)传递图形。另一方面,我可以找到一种替代方法,即将 HttpResponse 对象作为嵌入 html 文档的对象切换为上下文对象。我添加了修改后的代码。

以上是关于Django:如何将每个图形放在页面上而不保存它的主要内容,如果未能解决你的问题,请参考以下文章

我想弹出我自己的对话框(将文件保存在服务器上而不询问目标路径位置)而不是 adobe 的另存为对话框

执行@PostMapping 并留在页面上而不进行重定向

当手指在屏幕上而不抬起时,javascript动画在ios safari webkit浏览器中停止

如何将鼠标悬停在子元素上而不悬停在 CSS 中的父元素上?

Django - 插入而不返回已保存对象的 ID

在每个 Django 页面中传递一个对象