Piddle Graphics Online
Pages: 1, 2
Putting it Together: the View Page
With what we've learned and a little bit of HTML,
view.cgi is easy:
- first, print the content type;
- second, open the shelf and retrieve
- third, use the HTML
<img>tag to display the image (by setting the
srcattribute to chart.cgi);
- finally, display a link to edit each task.
The script is mostly plain HTML or code we've already seen, except for the last item, displaying a link to edit each task. This requires a loop:
# display the tasks as links:
for row in range(len(tasks)):
print '<li><a href="controller.cgi?action=edit&row=%i">%s</a>' \
% (row, tasks[row]["label"])
print ' [<a href="controller.cgi?action=delete&row=%i">delete<a>]</li>' \
Make sure that the web server has rights to read and write
model.shelf, and load
view.cgi in your
browser. If you run this cgi script now, you will see a broken image
and the list of tasks. Next we will work on the chart.
Displaying the Image
To create the image, we'll use the original gannt chart code, with three major changes. The new version will
- read the variables '
tasks', and '
titles' out of our shelf;
- set the
- write the generated image to standard output.
The first two changes are simple; the third is trickier. In theory,
we'd just save the piddle canvas to
sys.stdout, but there
are two problems with this approach.
The first problem is that
piddlePIL doesn't allow
saving images to file objects. Since it comes with full source,
however, we can fix it ourselves. Search in
save method. You'll see the problem. A couple
lines down, there's a bit of code that says:
if hasattr(file, 'write'): raise 'fileobj not implemented for piddlePIL'
Replace that with the following:
if hasattr(file, 'write'): self._image.save(file, format) return
Now, displaying the image on the web is easy. Here's the code, from
the bottom part of
print "content-type: image/jpeg" print import sys c.save(file=sys.stdout, format="jpeg")
The second problem only happens under Windows: the output gets
stdout is not in binary mode by
default. The fix is arcane, but concise:
import os, sys if sys.platform=="win32": import msvcrt msvcrt.setmode(sys.__stdin__.fileno(), os.O_BINARY) msvcrt.setmode(sys.__stdout__.fileno(), os.O_BINARY)
Place this before the content-type line and
should have no problem displaying the image.
Last Piece: the Controller
The controller is in charge of managing our data. Essentially, it does four things:
- displays a form to add a task;
- displays a form to edit an existing task;
- saves a new or updated task;
- deletes an existing task
controller.cgi shows the "add" form. A
action tells it to do something else. We
action, either as part of a query string (data
following the question mark in a URL) or via a form submission. The
cgi module can handle either method through the
FieldStorage can be
treated almost like a dictionary, although it doesn't implement
every dictionary method. For simple cases like this, it returns values
cgi.MiniFieldStorage objects. The following code
FieldStorage in action:
import cgi request = cgi.FieldStorage() action = "add" # by default if request.has_key("action"): action = request["action"].value
controller.cgi, a set of if/elif blocks looks at
action parameter and calls the appropriate
function. In a sense, the controller is several CGI scripts rolled
into one. We could have broken these into separate files, but I prefer
to keep related logic together.
Some of the available actions don't return a page to the browser
but, instead, redirect it to another page. In our case,
deleteTask both call
backToView, which returns a
rather than a content type. The following line sends the browser back
to the view page:
print "Location: view.cgi"
The rest of
controller.cgi, including the code to save
and delete tasks, is pretty straightforward. Consult the source for details.
That's it for this whirlwind tour of the gantt chart CGI application. To recap, we've seen how to store and retrieve data from a python shelf, communicate with the browser through CGI, and use piddlePIL to generate graphics in real time on the Web.