ChartDirector Ver 5.0 (Python Edition)

Pass Data as HTTP Query Parameters




In this example, we will introduce a technique where the database query is performed in the containing HTML page, and the data is passed to the ChartDirector script as HTTP GET query parameters. Using this method, it is possible to perform one database query and feed the data to multiple charts.

The user will select a year from a HTML form and press OK. The web server will query a database to obtain the necessary data, and return a web page containing the bar chart and the line chart for the selected year.

The code for producing the HTML form is listed below.

The code outputs a drop down select list to allow the user to select a year. Based on the selected year, it queries the database and read the data into arrays. The data are then serialized into comma delimited strings using the "string.join" function. Two <IMG> tags are used to invoke two scripts for charts generation, where the data are passed in as HTTP GET query parameters using the comma delimited strings.

[CGI Version] pythondemo_cgi\dbdemo2.py
#!/usr/bin/python
from pychartdir import *
import cgi

# Get HTTP query parameters
query = cgi.FieldStorage()


# The currently selected year
try :
    selectedYear = int(query["year"].value)
except :
    selectedYear = 2005

#
# Query the database to get monthly reveunes for software, hardware and services for
# the year. In this demo, we will use random numbers instead of a real database.
#
rantable = RanTable(selectedYear, 3, 12)
rantable.setCol(0, 30 * (selectedYear - 1990),  80 * (selectedYear - 1990))
rantable.setCol(1, 30 * (selectedYear - 1990),  80 * (selectedYear - 1990))
rantable.setCol(2, 30 * (selectedYear - 1990),  80 * (selectedYear - 1990))

software = rantable.getCol(0)
hardware = rantable.getCol(1)
services = rantable.getCol(2)

# Serialize the data into a string to be used as HTTP query parameters
httpParam = "year=%s&software=%s&hardware=%s&services=%s" % (selectedYear,
    string.join(map(str, software), ","), string.join(map(str, hardware), ","),
    string.join(map(str, services), ","))

#
# The following code generates the <option> tags for the HTML select box, with the
# <option> tag representing the currently selected year marked as selected.
#

optionTags = [None] * (2005 - 1994 + 1)
for i in range(1994, 2005 + 1) :
    if i == selectedYear :
        optionTags[i - 1994] = "<option value='%s' selected>%s</option>" % (i, i)
    else :
        optionTags[i - 1994] = "<option value='%s'>%s</option>" % (i, i)
selectYearOptions = string.join(optionTags, "")

print("Content-type: text/html\n")
print("""
<html>
<body style="margin:5px 0px 0px 5px">
<div style="font-size:18pt; font-family:verdana; font-weight:bold">
    Database Integration Demo (2)
</div>
<hr style="border:solid 1px #000080" />
<div style="font-size:10pt; font-family:verdana; width:600px">
This example demonstrates creating a chart using data from a database. The database
query is performed in the containing HTML page. The data are then passed to the chart
generation pages as HTTP GET parameters.
<ul>
    <li><a href="viewsource.py?file=%(SCRIPT_NAME)s">
        View containing HTML page source code
    </a></li>
    <li><a href="viewsource.py?file=dbdemo2a.py">
        View chart generation page source code for upper chart
    </a></li>
    <li><a href="viewsource.py?file=dbdemo2b.py">
        View chart generation page source code for lower chart
    </a></li>
</ul>
<form>
    I want to obtain the revenue data for the year
    <select name="year">
        %(selectYearOptions)s
    </select>
    <input type="submit" value="OK">
</form>
</div>

<img src="dbdemo2a.py?%(httpParam)s">
<br><br>
<img src="dbdemo2b.py?%(httpParam)s">
</body>
</html>
""" % {
    "SCRIPT_NAME" : os.environ["SCRIPT_NAME"],
    "selectYearOptions" : selectYearOptions,
    "httpParam" : httpParam
    })

The <IMG> tags in the above code invoke "dbdemo2a.py" and "dbdemo2b.py" for charts generation. In "dbdemo2a.py" and "dbdemo2b.py", the data is retrieved from the HTTP GET query parameters and deserialized back into arrays by using the "string.split" function. The data are then used to generate the charts.

[CGI Version] pythondemo_cgi\dbdemo2a.py
#!/usr/bin/python
from pychartdir import *
import cgi

# Get HTTP query parameters
query = cgi.FieldStorage()

#
# Retrieve the data from the query parameters
#

selectedYear = query["year"].value

software = map(float, string.split(query["software"].value, ","))
hardware = map(float, string.split(query["hardware"].value, ","))
services = map(float, string.split(query["services"].value, ","))

#
# Now we obtained the data into arrays, we can draw the chart using ChartDirector
#

# Create a XYChart object of size 600 x 300 pixels, with a light grey (eeeeee)
# background, black border, 1 pixel 3D border effect and rounded corners.
c = XYChart(600, 300, '0xeeeeee', '0x000000', 1)
c.setRoundedFrame()

# Set the plotarea at (60, 60) and of size 520 x 200 pixels. Set background color to
# white (ffffff) and border and grid colors to grey (cccccc)
c.setPlotArea(60, 60, 520, 200, '0xffffff', -1, '0xcccccc', '0xccccccc')

# Add a title to the chart using 15pts Times Bold Italic font, with a light blue
# (ccccff) background and with glass lighting effects.
c.addTitle("Global Revenue for Year %s" % (selectedYear), "timesbi.ttf", 15
    ).setBackground('0xccccff', '0x000000', glassEffect())

# Add a legend box at (70, 32) (top of the plotarea) with 9pts Arial Bold font
c.addLegend(70, 32, 0, "arialbd.ttf", 9).setBackground(Transparent)

# Add a line chart layer using the supplied data
layer = c.addLineLayer2()
layer.addDataSet(software, '0xff0000', "Software").setDataSymbol(CircleShape, 9)
layer.addDataSet(hardware, '0x00ff00', "Hardware").setDataSymbol(DiamondShape, 11)
layer.addDataSet(services, '0xffaa00', "Services").setDataSymbol(Cross2Shape(), 11)

# Set the line width to 3 pixels
layer.setLineWidth(3)

# Set the x axis labels. In this example, the labels must be Jan - Dec.
labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct",
    "Nov", "Dec"]
c.xAxis().setLabels(labels)

# Set the y axis title
c.yAxis().setTitle("USD (Millions)")

# Set axes width to 2 pixels
c.xAxis().setWidth(2)
c.yAxis().setWidth(2)

# Output the chart in PNG format
print("Content-type: image/png\n")
binaryPrint(c.makeChart2(PNG))

[CGI Version] pythondemo_cgi\dbdemo2b.py
#!/usr/bin/python
from pychartdir import *
import cgi

# Get HTTP query parameters
query = cgi.FieldStorage()

#
# Retrieve the data from the query parameters
#

selectedYear = query["year"].value

software = map(float, string.split(query["software"].value, ","))
hardware = map(float, string.split(query["hardware"].value, ","))
services = map(float, string.split(query["services"].value, ","))

#
# Now we obtained the data into arrays, we can draw the chart using ChartDirector
#

# Create a XYChart object of size 600 x 300 pixels, with a light grey (eeeeee)
# background, black border, 1 pixel 3D border effect and rounded corners.
c = XYChart(600, 300, '0xeeeeee', '0x000000', 1)
c.setRoundedFrame()

# Set the plotarea at (60, 60) and of size 520 x 200 pixels. Set background color to
# white (ffffff) and border and grid colors to grey (cccccc)
c.setPlotArea(60, 60, 520, 200, '0xffffff', -1, '0xcccccc', '0xccccccc')

# Add a title to the chart using 15pts Times Bold Italic font, with a dark green
# (006600) background and with glass lighting effects.
c.addTitle("Global Revenue for Year %s" % (selectedYear), "timesbi.ttf", 15,
    '0xffffff').setBackground('0x006600', '0x000000', glassEffect(ReducedGlare))

# Add a legend box at (70, 32) (top of the plotarea) with 9pts Arial Bold font
c.addLegend(70, 32, 0, "arialbd.ttf", 9).setBackground(Transparent)

# Add a stacked area chart layer using the supplied data
layer = c.addAreaLayer2(Stack)
layer.addDataSet(software, '0x40ff0000', "Software")
layer.addDataSet(hardware, '0x4000ff00', "Hardware")
layer.addDataSet(services, '0x40ffaa00', "Services")

# Set the area border color to the same as the fill color
layer.setBorderColor(SameAsMainColor)

# Set the x axis labels. In this example, the labels must be Jan - Dec.
labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct",
    "Nov", "Dec"]
c.xAxis().setLabels(labels)

# Set the y axis title
c.yAxis().setTitle("USD (Millions)")

# Set axes width to 2 pixels
c.xAxis().setWidth(2)
c.yAxis().setWidth(2)

# Output the chart in PNG format
print("Content-type: image/png\n")
binaryPrint(c.makeChart2(PNG))