Serving images with CairoPlot and Django
I’ve been experiencing with Django lately, and I must say it’s amazing. I’m quite new to the scaffolding frameworks world, so I can’t really says how it compares to it’s brother Ruby On Rails.
But one thing is for sure, I think there’s a new version of RoR or ruby out, and all the tutorials I found were outdated, and finding help/ressources seemed so much easier for django than RoR.
Enough with the intro, I’m doing a little project in Django to edit data using a spearsheet (something similar to google docs). You can choose the rows and column via an interface, and a spreadsheet is generated allowing to edit the value of a couple {Row,Col}.
And I wanted to generate charts of the data contained in the spreadsheet, I stumbled upon CairoPlot, which is a nice and simple little library that allows you to generate charts in python using cairo. (See this blog post for examples, the site and more generally the internet has no information on cairoPlot sadly).
So I a hube n00b, but I finally succeeded in serving dynamic charts using CairoPlot in Django. And I thought I’ll share my experience since I had to hack into the library’s code to use it properly.
CairoPlot allows you with a simple line to generate a chart …. but to a file. I wanted to generate a dynamic image for my django template, not a file.
My template looks like this:
<img src="/generateChart"/>
And my /generateChart view is:
def gen_chart(request):
heigth = 600
width = 400
data = {"OK" : 50, "KO" : 20, "Easy fix": 30}
background = cairo.LinearGradient(300, 0, 300, 400)
background.add_color_stop_rgb(0,0,0.4,0)
background.add_color_stop_rgb(1.0,0,0.1,0)
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, heigth, width)
context = cairo.Context(surface)
colors = [ (50.0/255, 205.0/255, 50.0/255),
(255.0/255, 0/255, 0/255),
(210.0/255, 105.0/255, 30.0/255) ]
pp = CairoPlot.PiePlot(surface, data, heigth, width, background = None, gradient = True, shadow = True, series_colors = colors )
pp.render()
response = HttpResponse(mimetype="image/png")
pp.surface.write_to_png(response)
return response
The key here is not to call the regulare CairoPlot.pie_plot() function, which tries to save the image directly, but to call the PiePlot constructor with a cairo.ImageSurface as the first argument, get the created object, get it’s surface and call write_to_png(response) on it. And most importantly, create the correct HttpReponse object and write the png to the response object.
This must be very confusing, but I wrote this very quickly :P

