除了将模型查询结果和其他变量发送到Django模板之外,还发送绘图图像/对象

时间:2018-10-11 00:59:15

标签: python django matplotlib

请记住,我是Django和Web编程的新手。

我正在尝试做一些看似简单的事情,但我无法弄清楚:

我有一个“对象查看器”模板,用于显示有关从数据库中选择的单个对象的信息,我想在页面上包括一个图形。

models.py:

class MaxExtent(models.Model):

    id = models.IntegerField(primary_key=True)
    geoName = models.CharField('Geounit name (territories are unique geounits)', max_length=40, null=True)
    sovereignty = models.CharField('Sovereign country name', max_length=32, null=True)
    lakeName = models.CharField('GLWD Lake name', max_length=50)
    areaMax = models.FloatField('Max Extent area (km^2)')
    area2000 = models.FloatField('2000 area (km^2)')
    area2001 = models.FloatField('2001 area (km^2)')
    area2002 = models.FloatField('2002 area (km^2)')
    area2003 = models.FloatField('2003 area (km^2)')
    area2004 = models.FloatField('2004 area (km^2)')
    area2005 = models.FloatField('2005 area (km^2)')
    area2006 = models.FloatField('2006 area (km^2)')
    centerLat = models.FloatField('Latitude of centroid')
    centerLon = models.FloatField('Longitude of centroid')

    poly = models.MultiPolygonField()

    def __str__(self): # default field for string representation

        if self.lakeName:
            return "ID {}: {} ({}, {})".format(self.id, self.lakeName, self.centerLon, self.centerLat)
        else:
            return "ID {}: Not named ({}, {})".format(self.id, self.centerLon, self.centerLat)

views.py:

from django.shortcuts import get_object_or_404, render    
from django.forms import ModelForm
from .models import MaxExtent
from .functions import chart_object_areas

# Object viewer
def objectViewer(request, req_id):
    waterBody = get_object_or_404(MaxExtent, pk = req_id)

    displayFields = [str(f.name) for f in MaxExtent._meta.get_fields()]
    class MaxExtentForm(ModelForm):
        class Meta:
            model = MaxExtent
            fields = displayFields
    fields = MaxExtentForm(instance=waterBody)

    areas = [waterBody.area2000, waterBody.area2001, waterBody.area2002, waterBody.area2003, waterBody.area2004, waterBody.area2005, waterBody.area2006]
    years = [yr for yr in range(2000,2007)]
    # get the bar plot with best fit line on top
    return_chart = chart_object_areas(X = years, Y = areas, waterBody.slope, waterBody.intercept) # UPDATE

    context = {'waterBody': waterBody, 'displayFields': fields, 'chart': return_chart} # UPDATE - tried sending object to template

    return render(request, 'waterExplorer/objectViewer.html', context)

我可以显示模板代码,但我认为这不会有所帮助。只是知道它成功使用waterBody和displayFields以及对象的映射显示了属性信息。

现在我的问题...

我正在学习教程here,该教程使用matplotlib创建图表并将其呈现在模板中。我正在尝试使用模型中的信息创建一个简单的条形图(area2000到area2006是我的Y,而year--2000、2001,...,2006是X)。我有一个脚本,可以根据从模型中检索到的信息来创建该图(functions.chart_object_area);目前正在使用matplotlib,如本教程中所述。遵循示例1(请参见上面的example和views.py)在views.py中调用此方法并返回要渲染的对象

但是,除了waterBody和displayFields参数之外,如何返回f.getValue()?本教程将返回图表,如下所示:

    return HttpResponse(f.getvalue(), content_type="image/png")

但是我要返回:

    context = {'waterBody': waterBody, 'displayFields': form}

那我该如何结合两者,以便除了显示我已有的其他东西外,还可以显示该图?

我正在使用Django 1.11版

UPDATE :我已经更新了views.py中的代码,以指示如何获取要发送到图表函数的变量(请参阅#UPDATE),并在此处添加chart_object_areas函数。 。我还在views.py中进行了更新,以表明我尝试将输出图传递给模板:

functions.py:

import sys
from django.http import HttpResponse
import matplotlib as mpl
mpl.use('Agg') # Required to redirect locally
import matplotlib.pyplot as plt
import numpy as np
from numpy.random import rand

import cStringIO

def chart_object_areas(X, Y, slope, intercept):

    plt.ylim(0.0, np.max(Y)+(np.mean(Y)/3))
    plt.xlim(np.min(X)-1, np.max(X)+1)
    plt.ylabel('Area ($km^2$)')
    plt.xlabel('Year')
    plt.bar(X, Y)

    # plot the best fit line too
    fitY = [(slope*x + intercept) for x,d in enumerate(X)]
    plt.plot(X, fitY, color='black')


    plt.savefig('test-plot.png')
    f = cStringIO.StringIO() # redirect per tutorial
    plt.savefig(f, format="png", facecolor=(0.95,0.95,0.95))
    plt.clf()

    return f.getvalue() # per tutorial

如您所见,我保存了图形并确认函数正在生成图。但是,当我尝试像这样在模板中呈现它时:

{{ chart | safe }}

没有任何显示。我假设这是因为我传递给模板的方式[在教程中,他在返回响应时使用content_type =“ image / png”,并且在将上下文发送到时我不知道该怎么做render()]。

同样,我正在按照教程here学习在Django中使用matplotlib。

0 个答案:

没有答案