Using PyCha with Django

Fri 25 February 2011
By stu

A quick post on using Python Charts to generate nice SVG charts for your django website (I've had the code hanging around for ages - so should just post it). The code is based on the examples there, here I integrate it into Django.

To install you'll need to do

pip install pycha

Heres the code for a simple view to output a chart directly to SVG:

{: .alignnone .size-full .wp-image-291 width="401" height="316"}

```

views.py

from StringIO import StringIO from django.http import HttpResponse

import cairo

def colors(request): in_req = 1

svg_buffer = StringIO()

width, height = (500, 400)
surface = cairo.SVGSurface(svg_buffer, width, height)

dataSet = (
 ('dataSet 1', ((0, 1), (1, 3), (2, 2.5))),
 ('dataSet 2', ((0, 2), (1, 4), (2, 3))),
 ('dataSet 3', ((0, 5), (1, 1), (2, 0.5))),
)

options = {
   'legend': {'hide': True},
   'background': {'color': '#f0f0f0'},
}

#import pycha.bar
#chart = pycha.bar.VerticalBarChart(surface, options)

import pycha.line
chart = pycha.line.LineChart(surface, options)
chart.addDataset(dataSet)
chart.render()

del chart
del surface

response = ''
response = HttpResponse(mimetype='image/svg+xml')
svg_buffer.seek(0)
response.write( svg_buffer.read() )
return response

```

The basic idea is that - instead of the chart outputting to an svg file, the output goes to a buffer, this is triggered by calling the destructors of the chart and it's cairo surface.  Once the data is in the buffer, it is rewound and played back to the Http Response.

Inline SVG

As is, this won't work as inline svg, because outputting the XML preamble in the middle of the page will cause problems.  Below is an example that let's you decide if you need the preamble (full SVG output), or not (SVG fragment for inclusion in a page or another SVG):

```

Create your views here.

from StringIO import StringIO from django.http import HttpResponse from django.shortcuts import render_to_response

import cairo

XML_PREAMBLE = '<?xml version="1.0" encoding="UTF-8"?>'

def colors_chart(inline = False): """ Generate colours chart

Set inline to True to disable the XML preamble
"""
in_req = 1

svg_buffer = StringIO()

width, height = (500, 400)
surface = cairo.SVGSurface(svg_buffer, width, height)

dataSet = (
 ('dataSet 1', ((0, 1), (1, 3), (2, 2.5))),
 ('dataSet 2', ((0, 2), (1, 4), (2, 3))),
 ('dataSet 3', ((0, 5), (1, 1), (2, 0.5))),
)

options = {
   'legend': {'hide': True},
   'background': {'color': '#f0f0f0'},
}

import pycha.bar
chart = pycha.bar.VerticalBarChart(surface, options)

#import pycha.line
#chart = pycha.line.LineChart(surface, options)
chart.addDataset(dataSet)
chart.render()

del chart
del surface

response = ''

if inline:
    svg_buffer.seek(len(XML_PREAMBLE))
else:
    svg_buffer.seek(0)
return svg_buffer.read()

def colors_svg(request): """ render a pure SVG chart """ response = HttpResponse(mimetype='image/svg+xml') response.write(colors_chart(inline = False)) return response

def index(request): """ render a chart into the template """ chart_svg = colors_chart(inline = True)

return render_to_response(
    'shapes_index.html',
    { "chart" : chart_svg },
    mimetype='application/xhtml+xml')

```

An example project with the above code is available here:
pycha_django

[EDIT 25/2/2011] Fixed PyCha URL