| 115 | |
| 116 | = Creating a Line chart = |
| 117 | The reportlab/graphics framework provides a Drawing object and many Shape objects, |
| 118 | which include primitive shapes, and high-level objects like charts and legends. You |
| 119 | can easily write your own too if you want to make dynamic bitmap buttons or fancy |
| 120 | dashboard apps. |
| 121 | |
| 122 | The usual pattern we follow is to create a Drawing class with all of your widgets, |
| 123 | some sensible default data, and any visual settings you want. Here is such a class, |
| 124 | which has a bar chart and a string for the chart title. |
| 125 | |
| 126 | {{{ |
| 127 | # mycharts.py |
| 128 | from reportlab.graphics.shapes import Drawing, String |
| 129 | from reportlab.graphics.charts.lineplots import LinePlot |
| 130 | from reportlab.graphics.charts.lineplots import ScatterPlot |
| 131 | from reportlab.lib import colors |
| 132 | from reportlab.graphics.charts.legends import Legend |
| 133 | from reportlab.graphics.charts.textlabels import Label |
| 134 | from reportlab.graphics.widgets.markers import makeMarker |
| 135 | |
| 136 | |
| 137 | class MyLineChartDrawing(Drawing): |
| 138 | def __init__(self, width=600, height=400, *args, **kw): |
| 139 | apply(Drawing.__init__,(self,width,height)+args,kw) |
| 140 | self.add(LinePlot(), name='chart') |
| 141 | |
| 142 | self.add(String(200,180,'Hello World'), name='title') |
| 143 | |
| 144 | #set any shapes, fonts, colors you want here. We'll just |
| 145 | #set a title font and place the chart within the drawing. |
| 146 | #pick colors for all the lines, do as many as you need |
| 147 | self.chart.x = 20 |
| 148 | self.chart.y = 30 |
| 149 | self.chart.width = self.width - 100 |
| 150 | self.chart.height = self.height - 75 |
| 151 | self.chart.lines[0].strokeColor = colors.blue |
| 152 | self.chart.lines[1].strokeColor = colors.green |
| 153 | self.chart.lines[2].strokeColor = colors.yellow |
| 154 | self.chart.lines[3].strokeColor = colors.red |
| 155 | self.chart.lines[4].strokeColor = colors.black |
| 156 | self.chart.lines[5].strokeColor = colors.orange |
| 157 | self.chart.lines[6].strokeColor = colors.cyan |
| 158 | self.chart.lines[7].strokeColor = colors.magenta |
| 159 | self.chart.lines[8].strokeColor = colors.brown |
| 160 | |
| 161 | self.chart.fillColor = colors.white |
| 162 | self.title.fontName = 'Times-Roman' |
| 163 | self.title.fontSize = 18 |
| 164 | self.chart.data = [((0, 50), (100,100), (200,200), (250,210), (300,300), (400,500))] |
| 165 | self.chart.xValueAxis.labels.fontSize = 12 |
| 166 | self.chart.xValueAxis.forceZero = 0 |
| 167 | self.chart.xValueAxis.gridEnd = 115 |
| 168 | self.chart.xValueAxis.tickDown = 3 |
| 169 | self.chart.xValueAxis.visibleGrid = 1 |
| 170 | self.chart.yValueAxis.tickLeft = 3 |
| 171 | self.chart.yValueAxis.labels.fontName = 'Times-Roman' |
| 172 | self.chart.yValueAxis.labels.fontSize = 12 |
| 173 | self.title.x = self.width/2 |
| 174 | self.title.y = 0 |
| 175 | self.title.textAnchor ='middle' |
| 176 | self.add(Legend(),name='Legend') |
| 177 | self.Legend.fontName = 'Times-Roman' |
| 178 | self.Legend.fontSize = 12 |
| 179 | self.Legend.x = self.width |
| 180 | self.Legend.y = 85 |
| 181 | self.Legend.dxTextSpace = 5 |
| 182 | self.Legend.dy = 5 |
| 183 | self.Legend.dx = 5 |
| 184 | self.Legend.deltay = 5 |
| 185 | self.Legend.alignment ='right' |
| 186 | self.add(Label(),name='XLabel') |
| 187 | self.XLabel.fontName = 'Times-Roman' |
| 188 | self.XLabel.fontSize = 12 |
| 189 | self.XLabel.x = 85 |
| 190 | self.XLabel.y = 5 |
| 191 | self.XLabel.textAnchor ='middle' |
| 192 | #self.XLabel.height = 20 |
| 193 | self.XLabel._text = "" |
| 194 | self.add(Label(),name='YLabel') |
| 195 | self.YLabel.fontName = 'Times-Roman' |
| 196 | self.YLabel.fontSize = 12 |
| 197 | self.YLabel.x = 2 |
| 198 | self.YLabel.y = 80 |
| 199 | self.YLabel.angle = 90 |
| 200 | self.YLabel.textAnchor ='middle' |
| 201 | self.YLabel._text = "" |
| 202 | self.chart.yValueAxis.forceZero = 1 |
| 203 | self.chart.xValueAxis.forceZero = 1 |
| 204 | }}} |
| 205 | |
| 206 | = Integrating into Django = |
| 207 | |
| 208 | Now we add a view to our ''views.py''. |
| 209 | |
| 210 | {{{ |
| 211 | |
| 212 | def linechart(request): |
| 213 | |
| 214 | #instantiate a drawing object |
| 215 | d = MyLineChartDrawing() |
| 216 | |
| 217 | #extract the request params of interest. |
| 218 | #I suggest having a default for everything. |
| 219 | |
| 220 | |
| 221 | d.height = 300 |
| 222 | d.chart.height = 300 |
| 223 | |
| 224 | |
| 225 | d.width = 300 |
| 226 | d.chart.width = 300 |
| 227 | |
| 228 | d.title.text = request.session.get('Some custom title') |
| 229 | |
| 230 | |
| 231 | |
| 232 | d.XLabel._text = request.session.get('X Axis Labell') |
| 233 | d.YLabel._text = request.session.get('Y Axis Label') |
| 234 | |
| 235 | d.chart.data = [((1,1), (2,2), (2.5,1), (3,3), (4,5)),((1,2), (2,3), (2.5,2), (3.5,5), (4,6))] |
| 236 | |
| 237 | |
| 238 | |
| 239 | labels = ["Label One","Label Two"] |
| 240 | if labels: |
| 241 | cnt=0 |
| 242 | # set colors in the legend |
| 243 | d.Legend.colorNamePairs = [] |
| 244 | for label in labels: |
| 245 | d.Legend.colorNamePairs.append((d.chart.lines[cnt].strokeColor,label)) |
| 246 | cnt=cnt+1 |
| 247 | |
| 248 | |
| 249 | #get a GIF (or PNG, JPG, or whatever) |
| 250 | binaryStuff = d.asString('gif') |
| 251 | return HttpResponse(binaryStuff, 'image/gif') |
| 252 | }}} |
| 253 | |
| 254 | |
| 255 | Finally, you need a URL mapping. In this case I have added this: |
| 256 | |
| 257 | {{{ |
| 258 | (r'^charts/line/$', 'myapp.views.linechart'), |
| 259 | |
| 260 | }}} |
| 261 | |
| 262 | Now you can start Django, point your browser at the URL with no arguments, |
| 263 | and should see the chart. Then try out a few parameters such as |
| 264 | http://localhost:8000/charts/line?title=awesome |
| 265 | and watch it redraw. |
| 266 | |