• Aucun résultat trouvé

Implementing Site Logic

Chapter 4. The Document Object Model

4.6 Building a Web Application

4.6.3 Implementing Site Logic

The Article and Storage classes are not web-oriented. They could be used in any type of application, as the articles are represented in XML, and the Storage class just handles their I/O to disk. Conceptually at least, you could use these classes anywhere to create an XML-based information store.

On the other hand, you could write a single CGI script that has all of the logic to store articles to disk and read them, as well as parse the XML, but then your articles and their utility would be trapped within the CGI script. By breaking core functionality off into discrete components, you're free to use the Article and Storage classes from any type of application you envision.

In order to manage web interaction with the article classes, we will create one additional class (ArticleManager) and one additional script (start.cgi). The ArticleManager class builds a web interface for article manipulation. It has the ability to display articles as HTML, to accept posted articles from a web form, and to handle user interaction with the site. The start.cgi script handles I/O from the web server and drives the ArticleManager.

4.6.3.1 The ArticleManager class

The ArticleManager class contains four methods for dealing with articles. The manager acts as a liaison between the article objects and the actual CGI script that interfaces with the web server (and, indirectly the user's browser).

The viewAll method picks all of the XML articles off the disk and creates a section of HTML hyperlinks linking to the articles. This method is called by the CGI script to create a page showing all of the article titles as links:

def viewAll(self):

"""Displays all XML files in the current working directory."""

print "<p>View All<br><br>"

# grab list of files in current directory fl = os.listdir(".")

for xmlFile in fl:

# weed out XML files

tname, ext = os.path.splitext(xmlFile) if ext == ".xml":

# create HTML link surrounding article name

print '<br><a href="start.cgi?cmd=v1a&af=%s">%s</a><br>' % (quote(xmlFile), tname)

The method is not terribly elegant. It simply reads the contents of the current directory, picks out the XML files, and strips the .xml extension off the name before displaying it as a link. The link connects back again to the same page (start.cgi), but this time with query string parameters that instruct start.cgi to invoke the viewOne method to view the content of a single article. The quote function imported from urllib is used to escape special characters in the filename that may cause problems for the browser. URL construction and quoting is discussed in more detail in Chapter 8.

The viewOne method uses the storage object to reanimate an article stored on disk. Once the article instance is created, its data members are mined (one by one), and wrapped with HTML for display in the browser:

def viewOne(self, articleFile):

""" takes an article file name as a parameter and creates and displays an article object for it.

"""

# create storage and article objects store = Storage( )

art = store.load(articleFile)

# Write HTML to browser (standard output) print "<p>Title: " + art.title + "<br>"

print "Author: " + art.author + "<br>"

print "Date: " + art.time + "<br>"

print "<table width=500><tr><td>" + art.contents print "</td></tr></table></p>"

It's important to note here that the parameter handed to viewOne is a real filename, not just the title of the XML document.

The postArticle method is probably the simplest method discussed yet, as its job is simply to create HTML. The HTML represents a submittal form whereby users can write new articles and present them to the server for ultimate storage in XML. Since the HTML form does not change, this method can simply print the value of a constant that contains the form as a string.

The postArticleData method is slightly more complicated. Its job is to extract key/value pairs from a submitted HTTP form, and create an XML article based on the obtained values.

Once the XML is created, it must be stored to disk. It does this by creating an article object and setting the members to values retrieved from the form, then using the Storage class to save the article.

def postArticleData(self, form):

"""Accepts actual posted form data, creates and stores an article object."""

# populate an article with information from the form art = Article()

art.title = form["title"].value art.author = form["author"].value art.contributor = form["contrib"].value art.contents = form["contents"].value

# store the article store = Storage() store.save(art)

Example 4-8 shows ArticleManager.py in its entirety.

Example 4-8. ArticleManager.py

# ArticleManager.py import os

from urllib import quote from article import Article from storage import Storage

class ArticleManager:

"""Manages articles for the web page.

Responsible for creating, loading, saving, and displaying articles."""

def viewAll(self):

"""Displays all XML files in the current working directory."""

print "<p>View All<br><br>"

# grab list of files in current directory fl = os.listdir(".")

for xmlFile in fl:

# weed out XML files

tname, ext = os.path.splitext(xmlFile) if ext == ".xml":

# create HTML link surrounding article name

print '<br><a href="start.cgi?cmd=v1a&af=%s">%s</a><br>' \ % (quote(xmlFile), tname)

def viewOne(self, articleFile):

"""Takes an article file name as a parameter and creates and displays an article object for it.

"""

# create storage and article objects store = Storage( )

art = store.load(articleFile)

# Write HTML to browser (standard output) print "<p>Title: " + art.title + "<br>"

print "Author: " + art.author + "<br>"

print "Date: " + art.time + "<br>"

print "<table width=500><tr><td>" + art.contents print "</td></tr></table></p>"

def postArticle(self):

"""Displays the article posting form."""

print POSTING_FORM

def postArticleData(self,form):

"""Accepts actual posted form data, creates and stores an article object."""

# populate an article with information from the form art = Article()

art.title = form["title"].value art.author = form["author"].value art.contributor = form["contrib"].value art.contents = form["contents"].value

# store the article store = Storage() store.save(art)

POSTING_FORM = '''\

<form method="POST" action="start.cgi?cmd=pd">

<p>

Title: <br><input type="text" length="40" name="title"><br>

Contributor:<br><input type="text" length="40" name="contrib"><br>

Author: <br><input type="text" length="40" name="author"><br>

Contents: <br><textarea rows="15" cols="80"

name="contents"></textarea><br>

<input type="submit">

</form>

'''