Using MatPlotLib to dynamically generate charts in a Django web service

Based on the work with Zope, the following is a recipe for displaying a chart using Django. You need to have a working Django installation, plus matplotlib, Anti-Grain, and numpy. In Debian testing, Django plus the following packages suffice:

1. python

2. python-numpy

3. python-numpy-ext

4. python-matplotlib

5. python-imaging

6. python-numeric

Example 1 - PIL Buffer

def chart(request):
    from PIL import Image as PILImage
    from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
    from matplotlib.figure import Figure
    from StringIO import StringIO
    fig = Figure()
    canvas = FigureCanvas(fig)
    ax = fig.add_subplot(111)
    ax.plot([1,2,3])
    ax.set_title('hi mom')
    ax.grid(True)
    ax.set_xlabel('time')
    ax.set_ylabel('volts')
    canvas.draw()
    size = canvas.get_renderer().get_canvas_width_height()
    buf=canvas.tostring_rgb()
    im=PILImage.fromstring('RGB', size, buf, 'raw', 'RGB', 0, 1)
    imdata=StringIO()
    im.save(imdata, format='JPEG')
    response = HttpResponse(imdata.getvalue(), mimetype='image/jpeg')
    return response

Example 1a - Unix Socket Pair

If the PIL buffer seems like a hack to you and you're running on an operating system that supports UNIX sockets, you can create a socket pair and use it read out image data.

def chart(request):
    from socket import socketpair
    from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
    from matplotlib.figure import Figure
    fig = Figure()
    canvas = FigureCanvas(fig)
    ax = fig.add_subplot(111)
    ax.plot([1,2,3])
    ax.set_title('hi mom')
    ax.grid(True)
    ax.set_xlabel('time')
    ax.set_ylabel('volts')
    canvas.draw()

    ins, outs = socket.socketpair()
    ins = ins.makefile('w')
    outs = outs.makefile('r')

    canvas.print_figure(ins)
    response = HttpResponse(outs, mimetype='image/png')
    return response

Example 2 - Cairo Backend

With the cairo backend you can write directly to a StringIO() object without using PIL.

from django.http import HttpResponse
def cairo_chart(request):
    import matplotlib
    matplotlib.use('Cairo')
    from matplotlib.figure import Figure
    from matplotlib.backends.backend_cairo import FigureCanvasCairo as FigureCanvas
    from StringIO import StringIO
    fig = Figure()
    canvas = FigureCanvas(fig)
    ax = fig.add_subplot(111)
    ax.plot([1,2,3])
    ax.set_title('hi mom')
    ax.grid(True)
    ax.set_xlabel('time')
    ax.set_ylabel('volts')
    canvas.draw()
    imdata=StringIO()
    fig.savefig(imdata,format='png')
    return HttpResponse(imdata.getvalue(), mimetype='image/png')


Cookbook/Matplotlib/Django (last edited 2007-06-28 20:59:49 by DavidSheets)