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 :
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.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 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):
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:% > 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 ... +----------------------------------------------------+
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.
To extract information from the database, you have to send it a SQL query. This is done as follows:# 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)
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")
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.r = msqlStoreResult() # Store the query results for i in range(0,nrows): # Loop over rows fetching the results row = msqlFetchRow(r) print row
The output of this program is as follows: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)
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")
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.msqlQuery(h,"select * from Items where item_number=13 or item_number=7 or item_number=23 or item_number=31")
#!/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:
The output of this script produces a list of categories with links to another CGI program 'titles.cgi' like this:#!/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)
<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
If you print out the session ID you receive, it will look something like this:from socket import * s = socket(AF_INET,SOCK_STREAM,0) s.connect("rustler.cs.uchicago.edu",11000) session_id = s.recv(64) s.close()
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 ...