Making charts and output them as images to the browser in Django

Simple graph made with matplotlib

Simple graph made with matplotlib

Lets say you are working on a website made in Django. And you want to make some nice looking graphs real time, as images from dynamic data. This can be done by using the python 2D graph library matplotlib. The library can be found in the debian package python-matplotlib. A simple graph showing a sine curve, seen to the right, can be generated in regular python using the following code(taken from this example):

from pylab import *
t = arange(0.0, 2.0, 0.01)
s = sin(2*pi*t)
plot(t, s, linewidth=1.0)
xlabel('time (s)')
ylabel('voltage (mV)')
title('About as simple as it gets, folks')

Output graph to browser from a Django view

If you want to output this graph as a PNG image to the browser from a view in Django, you can store the image in a string buffer and output this buffer using the HttpReponse class in Django and set the mime type to image/png.

from django.http import HttpResponse
from matplotlib import pylab
from pylab import *
import PIL, PIL.Image, StringIO
def showimage(request):
    # Construct the graph
    t = arange(0.0, 2.0, 0.01)
    s = sin(2*pi*t)
    plot(t, s, linewidth=1.0)
    xlabel('time (s)')
    ylabel('voltage (mV)')
    # Store image in a string buffer
    buffer = StringIO.StringIO()
    canvas = pylab.get_current_fig_manager().canvas
    pilImage = PIL.Image.frombytes("RGB", canvas.get_width_height(), canvas.tostring_rgb()), "PNG")
    # Send buffer in a http response the the browser with the mime type image/png set
    return HttpResponse(buffer.getvalue(), content_type="image/png")

16 Responses

  1. Anonymous says:

    What would be helpful is an FULL example from a CBV (meaning + template file).

  2. Praveen says:

    Thanks for the Notes.
    But how to render the image to html file ?
    I am unable pass it html file. Please help me

  3. ojas says:

    Couple of suggestions:

    As of April 2018:
    from string is replaced with frombytes
    user content_type instead of mimetype

  4. You don’t need io or cStringIO. You can just do:
    canvas = FigureCanvasAgg(f)
    response = HttpResponse(content_type=’image/png’)
    return response

  5. Anton says:


  6. Derek says:

    Can you show an example that involves creating and sending multiple chart images to the same page – I cannot get this to work.

  7. Satvir says:

    Thanku it was really helpful.

  8. noemi says:

    Hi! Thanks for your website, it is really useful. About the output graph to browser from a Django view, I wonder if instead of using HttpResponse we can use render_to_response and represent the graph in a specific html page. I’ve done something like this:

    # serialize to HTTP response
    response = HttpResponse(buffer.getvalue(), mimetype=”image/png”)
    return render_to_response(‘eQL/dev/showImage.html’, {‘response’:response})

    But I don’t know how to plot it in the html file.


  9. masood says:

    whats the book you prefer to learn python with that

  10. Nathan Moos says:

    you could use cStringIO…its faster

    • Erik Smistad says:

      I tried using cStringIO instead of StringIO and measured execution time using datetime. Both buffer types ran in about 0.25 seconds. I think this is because the code only performs one large write to the buffer. If you have a buffer with several writes and reads, cStringIO will probably be notably faster

Leave a Reply

Your email address will not be published.