Due : Friday, February 29, 1999. Midnight.
Please read this entire handout before you begin work.
The store is built around a relational database system that contains the current catalog of CDs, customer information, and individual orders. Unfortunately, this database doesn't have any sort of web-interface. Your job is to provide a web-interface to the database that allows customers to do the following :
Table : Items
-------------
item_number int
item_title char(50)
item_artist char(50)
item_price money
item_category char(15)
Table : OrderItem
-----------------
order_id char(50)
order_item int
order_quantity int
The Items table contains information about the CDs available in the catalog. The
OrderItem table contains information about a particular item that has been ordered.
The database also contains tables about customers and billing information, but you will not have to worry about that until the next project (security and authentication).
For debugging and to generally see what is in the database, you can use the program 'msql' as follows (things you type are in bold):
% > msql -h rustler project2
Welcome to the miniSQL monitor. Type \h for help.
mSQL > select item_title from Items
-> \g
Query OK. 32 row(s) modified or retrieved.
+----------------------------------------------------+
item_title
+----------------------------------------------------+
Zoot Suit Riot
Supposed Former Infatuation Junkie
The Dirty Boogie
The Book of Secrets
Before These Crowded Streets
Left of the Middle
Version 2.0
Adore
Whitechocolatespaceegg
From The Choirgirl Hotel
Kind of Blue
...
+----------------------------------------------------+
This interface to the database is really only used for debugging. For your CGI
scripts, you will need to access the database in a way that makes it easy to
extract information and produce HTML pages. mSQL has both a C API and its own
scripting language that are described in:
I will describe a Python interface to mSQL that has been installed on classes. You are free to use any interface to mSQL you can find, but I recommend sticking with the Python interface described here.
# Load the database module
from msql import *
# Connect to the database
h = msqlConnect("rustler.cs.uchicago.edu")
if h < 0:
print "Couldn't connect"
# Select the database
if msqlSelectDB(h,"project2") < 0:
print "Couldn't find the database"
# Do a bunch of stuff
...
# Close the database (when you are done)
msqlClose(h)
To extract information from the database, you have to send it a SQL query. This is done as follows:
Upon completion, the query function returns the number of rows returned from the database. To fetch the returned data, you have to do the following:nrows = msqlQuery(h,"select item_title from Items")
r = msqlStoreResult() # Store the query results
for i in range(0,nrows): # Loop over rows fetching the results
row = msqlFetchRow(r)
print row
This code simply loops over the number of rows and fetches each row, one by one. The
msqlFetchRow function returns the row as a Python tuple.
from msql import *
h = msqlConnect("rustler")
msqlSelectDB(h,"project2")
nrows = msqlQuery(h,"""select item_artist, item_title, item_price from Items
where item_category='Rock'""")
r = msqlStoreResult()
for i in range(0,nrows):
print """
Artist: %s
Title : %s
Price : $%s""" % msqlFetchRow(r)
msqlClose(h)
The output of this program is as follows:
Artist: Cherry Poppin' Daddies Title : Zoot Suit Riot Price : $11.88 Artist: Alanis Morissette Title : Supposed Former Infatuation Junkie Price : $12.58 Artist: Brian Setzer Orchestra Title : The Dirty Boogie Price : $11.88 Artist: Loreena McKennitt Title : The Book of Secrets Price : $11.88 Artist: Dave Matthews Band Title : Before These Crowded Streets Price : $11.88 Artist: Natalie Imbruglia Title : Left of the Middle Price : $11.88 Artist: Garbage Title : Version 2.0 Price : $11.88 Artist: Smashing Pumpkins Title : Adore Price : $14.99 Artist: Liz Phair Title : Whitechocolatespaceegg Price : $11.88 Artist: Tori Amos Title : From The Choirgirl Hotel Price : $12.99
This will return a distinct list of all of the available music categories. Currently, the database has five categories : 'Rock','Jazz','Country','Blues', and 'Offensive'.msqlQuery(h,"select distinct item_category from Items")
This will return a list of all items available in a given category. The '*' means that all five fields in the Items table will be returned. You will use this produce a listing of titles.msqlQuery(h,"select * from Items where item_category='Rock'")
This returns the item with a specific item number. You will use this to display information about a single item.msqlQuery(h,"select * from Items where item_number=13")
msqlQuery(h,"select * from Items where item_number=13 or item_number=7
or item_number=23 or item_number=31")
This would return items 13,7,23, and 31 from the database. You might use a
query like this to display the contents of a shopping cart.
#!/usr/local/classes/current/CS219/packages/bin/python
import cgi
from msql import *
import string
import sys
import os
# Any other modules you think are necesssary
# See what kind of method is being used (GET or POST)
method = os.environ["REQUEST_METHOD"]
if method == "POST":
clen = string.atoi(os.environ["CONTENT_LENGTH"])
query_string = sys.stdin.read(clen)
elif method == "GET":
try:
query_string = os.environ["QUERY_STRING"]
except:
query_string = ""
else:
print "\nCGI error"
sys.exit(1)
# Now parse the query string
query_data = cgi.parse_qs(query_string)
# Individual query parameters can be accessed like this
val = query_data["name"]
# Print the HTTP header
print "Content-type: text/html"
print ""
# Open up the database
h = msqlConnect("rustler.cs.uchicago.edu")
msqlSelectDB(h,"project2")
# Print a bunch of content
...
# Close the database and exit
msqlClose(h)
Each category would be a link to a page showing the available titles in that category.Available Categories
- Rock
- Jazz
- Country
- Blues
- Offensive
Here is a CGI script that produces the above listing:
#!/usr/local/classes/current/CS219/packages/bin/python
import sys
import cgi
from msql import *
import string
# Print a list of available categories
print "Content-type: text/html"
print ""
print """
<html>
<head>
<title>Available Categories</title>
</head>
<body bgcolor="#ffffff">
<h1>Available Categories</h1>
"""
print "<ul>"
# Open up the database
h = msqlConnect("rustler.cs.uchicago.edu")
msqlSelectDB(h,"project2")
nrows = msqlQuery(h,"select distinct item_category from Items")
r = msqlStoreResult()
for i in range(0,nrows):
category = msqlFetchRow(r)[0]
print """<li><a href="/cgi-bin/titles.cgi?category=%s">%s</a>""" %
(category,category)
print "</ul>"
print """
</body>
</html>
"""
# Close the database and exit
msqlClose(h)
The output of this script produces a list of categories with links to another CGI program
'titles.cgi' like this:
<ul> <li><a href="/cgi-bin/titles.cgi?category=Rock">Rock</a> <li><a href="/cgi-bin/titles.cgi?category=Jazz">Jazz</a> <li><a href="/cgi-bin/titles.cgi?category=Country">Country</a> <li><a href="/cgi-bin/titles.cgi?category=Blues">Blues</a> <li><a href="/cgi-bin/titles.cgi?category=Offensive">Offensive</a> </ul>
This listing will be produced in a manner very similar to the last CGI script--only the database query will be different.Jazz
Kind of BlueMiles DavisGershwin's World
Our price: $8.38
Herbie HancockA Love Supreme
Our price: $11.38
John Coltrane and Johnny HartmanCombustication
Our price: $12.99
Medeski Martin & Wood
Our price: $12.99
Again, this display is produced with a database query that asks for a specific item number (note : displaying a picture is optional).Kind of Blue
![]()
Miles Davis
Our Price: $8.38
from socket import *
s = socket(AF_INET,SOCK_STREAM,0)
s.connect("rustler.cs.uchicago.edu",11000)
session_id = s.recv(64)
s.close()
If you print out the session ID you receive, it will look something like this:
19991211226173210-18The motivation for using a session-id server is to provide a centralized service for producing unique identifiers. Since CGI programs only run for brief periods of time (and often in parallel with other CGI requests on a heavily loaded server), it can be difficult to produce a unique session identifier (also consider the possibility of everyone in class trying to produce unique identifiers). By using a centralized server, it can keep track of what id's have been previously assigned and always come up with a unique value that is halfway sensible (plus, it makes the project just a tad bit more evil--which is, of course, a good thing).
Set-Cookie: sessionid=19991211226173210-18; path=/; domain=classes.cs.uchicago.edu ... Content-type: text/html ...