Is it possible to output a graph from Matplotlib into Django like this?

5,153 views
Skip to first unread message

nai

unread,
Apr 11, 2011, 6:21:28 AM4/11/11
to Django users
This is the give example from Matplotlib for Django:

def simple(request):
import random

from matplotlib.backends.backend_agg import FigureCanvasAgg as
FigureCanvas
from matplotlib.figure import Figure
from matplotlib.dates import DateFormatter

fig=Figure()
ax=fig.add_subplot(111)
x=[]
y=[]
now=datetime.datetime.now()
delta=datetime.timedelta(days=1)
for i in range(10):
x.append(now)
now+=delta
y.append(random.randint(0, 1000))
ax.plot_date(x, y, '-')
ax.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d'))
fig.autofmt_xdate()
canvas=FigureCanvas(fig)
response=django.http.HttpResponse(content_type='image/png')
canvas.print_png(response)
return response

Is there anyway I can return the image like this `return
render_to_response('template.html', {'graph': <graph generated by
matplotlib or some other graphing package>}`

Xavier Ordoquy

unread,
Apr 11, 2011, 6:39:22 AM4/11/11
to django...@googlegroups.com

Hi,

Is there any reasons why you couldn't have a view that would just render the image and the other one that would have a img tag pointing to the first view ?
It is possible to embed an image in the web page, but I'm sure it goes against the best practices.

Regards,
Xavier.

Derek

unread,
Apr 11, 2011, 9:43:15 AM4/11/11
to Django users
Or use one view - create the image and write it to a given location,
and then pass the URL for it to the template doing the rendering? If
you need to keep the image permanently, it could be stored in a model
and referenced accordingly.

nai

unread,
Apr 11, 2011, 11:29:06 PM4/11/11
to Django users

I will try to the 2 views method and see how I get on but in it would
be great if you could answer my questions too!

Why does it go against best practices?

How would one go about doing it anyway?

nai

unread,
Apr 11, 2011, 11:55:54 PM4/11/11
to Django users
One reason why I don't quite like the idea is because I am writing a
reporting webapp and there are many different graphs that can
generated. Needing to write 2 views for 1 type of graph can get pretty
tedious!

On Apr 11, 6:39 pm, Xavier Ordoquy <xordo...@linovia.com> wrote:

Sam Walters

unread,
Apr 12, 2011, 12:03:57 AM4/12/11
to django...@googlegroups.com
Use python imaging:
http://www.pythonware.com/products/pil/

You can return a response with an image of the graph.

response = HttpResponse(status=200, mimetype="image/gif")
background.save(response, "GIF")
return response

There is no 'best practice for this' Some people i know use flash.
However dynamically generated images is good eg: no browser pluggins

cheers

sam_w

> --
> You received this message because you are subscribed to the Google Groups "Django users" group.
> To post to this group, send email to django...@googlegroups.com.
> To unsubscribe from this group, send email to django-users...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
>
>

nai

unread,
Apr 12, 2011, 12:19:28 AM4/12/11
to Django users
Actually, could you illustrate how you would go about using 2 views as
well? Thanks!

On Apr 11, 6:39 pm, Xavier Ordoquy <xordo...@linovia.com> wrote:

nai

unread,
Apr 12, 2011, 12:33:42 AM4/12/11
to Django users
You have to bear with me but where does background come from? So I can
use the save() method from the PIL library is that right?

And I can do something like this:

return render_to_response('template.html', {'graph':response})

Where graph is just a variable in my django template (and not <img
src="{{ graph }}" />)

Is that right?

Sam Walters

unread,
Apr 12, 2011, 2:00:27 AM4/12/11
to django...@googlegroups.com
Hi

How about one view that takes arguments as either POST or GET params?

> You have to bear with me but where does background come from? So I can
> use the save() method from the PIL library is that right?

Ok so you can load a canvas.

Just to illustrate here is a view that puts dots on a map *map is the canvas.

specifically:
try:
background = Image.open(image_path)
canvas = ImageDraw.Draw(background)
except IOError:
return HttpResponse(status=500)

Below is the full view...
I think this is what you want. Hope its makes things clearer.

def drawAllEvents(request, **kwargs):
import Image, ImageDraw
from datetime import datetime

image_path = getattr(settings,'HOME_DIR')+'templates/images/front.gif'

try:
background = Image.open(image_path)
canvas = ImageDraw.Draw(background)
except IOError:
return HttpResponse(status=500)

if background.mode is not 'P':
return HttpResponse(status=500)

aa = Airfield.objects.filter(locality__event__dates__start__gte=datetime.now()).values('airfield_lat_dec','airfield_long_dec')
ll = Location.objects.filter(locality__event__dates__start__gte=datetime.now()).values('location_lat_dec','location_long_dec')

#---------------------------------------------------------------------
def renderdot(latlon):
#scaling relative to aeroclub map (204, 165) in pixels
scale = float(Decimal(10)/Decimal(49))
mx = 120 - 36*scale
my = (-25 - (background.size[1] - 71)*scale)

xcoord1 = round((latlon[1] - mx)/scale);
ycoord1 = background.size[1] - round((latlon[0] - my)/scale);

#bounding box of the ellipse
xcoord2=xcoord1+5
ycoord2=ycoord1+5

canvas.ellipse([(xcoord1,ycoord1),(xcoord2, ycoord2)], fill=0)
#---------------------------------------------------------------------

for e in aa:
renderdot( (float(e['airfield_lat_dec']),
float(e['airfield_long_dec'])) )
for e in ll:
renderdot( (float(e['location_lat_dec']),
float(e['location_long_dec'])) )

response = HttpResponse(status=200, mimetype="image/gif")
background.save(response, "GIF")
return response

Sam Walters

unread,
Apr 12, 2011, 2:06:55 AM4/12/11
to django...@googlegroups.com
I mis-read this... basically you have one view and in the template you
are rendering you put HTML:


<img src="/some/path/to/a/view" />
<img src="/some/path/to/a/view" />

so that path will call your other views which return content as
content_type='image/png' or whatever specific format you're using.

what i was suggesting is you could have:

<img src="/some/path/to/a/view/?foo=1" />
<img src="/some/path/to/a/view/?foo=2" />
<img src="/some/path/to/a/view/?foo=3" />

So in your urls.py file it would parameratize 'foo' and in your view
method you could produce different responses based on the parameter.
Eg: in an other view i have i can pass lat and long coords as params
and it would put a dot on the map based on where that lat/long points
to.

Aryeh Leib Taurog

unread,
Apr 12, 2011, 2:49:38 PM4/12/11
to Django users
On Apr 11, 1:21 pm, nai <chng.nai...@gmail.com> wrote:
> Is there anyway I can return the image like this `return
> render_to_response('template.html', {'graph': <graph generated by
> matplotlib or some other graphing package>}`

As noted, images are almost always loaded independently. See, for
example, "Definition and Usage" of img tag here: http://www.w3schools.com/tags/tag_IMG.asp

If you would like to learn more about how to actually embed image in
the page, do a google search for Base64 data url. The relevant rfc is
here: http://www.faqs.org/rfcs/rfc2397.html
Note that this is of extremely limited application:
1. It doesn't work in all browsers.
2. Due to url length limits it won't work for large images

If you generate an svg image, you can embed that directly into the
page in the fashion you have suggested. Alas this also is not a cross
browser solution, but there are javascript/flash workarounds which may
suffice for you. Take a look at SVGWeb http://code.google.com/p/svgweb/

nai

unread,
Apr 13, 2011, 11:48:29 PM4/13/11
to Django users
Thanks for your help.

I went with 2 views, 1 for the image and 1 for the html.

Derek

unread,
Apr 14, 2011, 3:30:19 AM4/14/11
to Django users
Perhaps you could post your solution here, to help out others in
future?

Yunpeng Pan

unread,
May 21, 2016, 7:09:57 PM5/21/16
to Django users
This solution makes a lot of sense!
Reply all
Reply to author
Forward
0 new messages