maplotlib在django中的使用


maplotlib在django中的使用

matplotlib作为python的一个数据可视化包,一个画图包,真的非常不错。
通过下面这一段代码

    import matplotlib.pyplot as plt
    plt.matshow(price, cmap=plt.cm.Blues)
    plt.xticks(np.arange(1, int(row)), [])
    plt.yticks(np.arange(1, int(height)), [])
    plt.plot(path[:, 1] - 1, path[:, 0] - 1, linewidth=8)
    plt.colorbar()

我们可以创建一张图,这张图现在在内存中,我们想把这张图返回到网页上。
现在就有一个问题,我们改如何获取这张图的二进制数据呢?
解决方法1:先把它保存到本地,通过

plt.savefig()

然后读取,这确实可以。但是有个问题,如果多人同时访问网站呢?这时候,保存的文件就会被一次一次的覆盖,访问者最后看到的可能就不是自己想要的。
通过查看源码,和自己百度,最终找到了解决方案。

canvas = plt.get_current_fig_manager().canvas
canvas.draw()
buffer = io.BytesIO()
canvas.print_png(buffer)
data = buffer.getvalue()
buffer.close()

现在data就是我们想要的二进制图片数据,我们可以把它写到一个文件中看看

f=open('hh.png',mode='wb')
f.write(data)
f.close()

可以打开看看,确实是我们想要的图片。
现在我们的问题就是如何把二进制图片返回给页面

return HttpResponse(data, content_type="Image/png")

这样打开这个对应的url,就可以看到一张图片。
把我这个整个函数粘到这里

def plot(request):

    import numpy as np
    import pandas as pd
    import io
    import matplotlib.pyplot as plt
    price=request.session['price']
    height=request.session['height']
    row=request.session['row']
    ss=request.session['res']
    price = np.array(price)
    price=price.reshape(int(row),int(height))
    path = pd.Series(ss.split('\n')[1:-1]).apply(lambda x: x.split(' ')).values
    path = np.array(list(path)).astype('int')
    #上面的代码是我获取数据和对数据修改的代码,和此文章重点无关
    plt.matshow(price, cmap=plt.cm.Blues)
    plt.xticks(np.arange(1, int(row)), [])
    plt.yticks(np.arange(1, int(height)), [])
    plt.plot(path[:, 1] - 1, path[:, 0] - 1, linewidth=8)
    plt.colorbar()
    # plt.savefig()
    canvas = plt.get_current_fig_manager().canvas
    canvas.draw()
    buffer = io.BytesIO()
    canvas.print_png(buffer)
    data = buffer.getvalue()
    buffer.close()
    return HttpResponse(data, content_type="Image/png")

到这里其实就可以结束了,但是这样画出来的图就是固定的,不是我们想要的
所以我们需要获取画图的数据。画图的数据从哪里获取?
我这里采用了session的方法。

maplotlib在django中的使用_第1张图片

<form action="/result/" method="post">
        {% csrf_token %}
        <input type="hidden" name="row" value="{{row}}"/>
        <input type="hidden" name="height" value="{{height}}"/>
        {% for i in rows %}
            {% for j in heights %}
                <input type="text" name="{{i}},{{j}}"/>
            {%endfor%}
            <br>
        {%endfor%}
        <br>
        <input type="submit">
    form>
def result(request):
    height=request.POST.get('height','0')
    row=request.POST.get('row','0')
    paramer=str(row)+' '+str(height)+' '
    price=[]
    for i in range(int(row)):
        for j in range(int(height)):
            paramer=paramer+request.POST.get(str(i)+','+str(j),'0,0')+" "
            price.append(int(request.POST.get(str(i)+','+str(j),'0')))
    res=get_result(paramer)
    request.session['price'] = price
    request.session['height'] = height
    request.session['row'] = row
    request.session['res'] = res
    # return  HttpResponse(graphic, content_type="Image/png")
    return render(request,'algorithm/result.html',{'res':res.split('\n')[0]})
def get_result(paramer):
    import os
    hh=os.popen('4.exe '+paramer)
    ss=hh.read()
    hh.close()
    return ss

就是这样,也可以直接form提交到plot中,但不是我想要的效果

注意:使用session,必须运行

 python manage.py migrate

不然会出错。

你可能感兴趣的:(django)