Version 0.8.1, Webware for Python
Here we describe best practices for developing a web application using Webware.
The first task in developing an application is to set up the file structure in which you will be working.
It is possible to put your application in a subdirectory under WebKit/ and change WebKit/Configs/Application.config to add another context. But do not do this. Your application will be entwined with the Webware installation, making it difficult to upgrade Webware, and difficult to identify your own files from Webware files.
Instead you should use the script bin/MakeAppWorkDir.py. You should run it like:
$ python Webware/bin/MakeAppWorkDir -l --cvsignore -c context DIRECTORYNAME
This will create a directory DIRECTORYNAME that will contain a directory structure for your application. The options are:
When you do this, you'll see this directory structure:
404Text.txt Cache/ ErrorMsgs/ Logs/ WebKit.cgi lib/ AppServer* Configs/ Launch.py Sessions/ context/
Here's what the files and directories are for:
CVS is a useful tool for managing your application. It handles versioning, but it also makes it possible for other people to see snapshots of your progress, for multiple developers to collaborate and work on an application simultaneously, and it creates a sort of implicit file share. Even if you are the only developer on an application, CVS can be very helpful.
The working directory is a good place to start for creating a CVS module. Assuming you've set up cvs, you can get started simply by running:
$ cd WorkingDir $ cvs import -d 'initial import' WorkingDir ianb start @@ ib: check this command
You should use --cvsignore if you plan to do this. If you do then .cvsignore files will be added to each directory. These tell cvs to ignore certain files -- .pyc files, and all the files in certain directories (Cache, ErrorMsgs, Logs, and Sessions). You shouldn't otherwise notice these files, even if you aren't using CVS.
If you are using CVS or otherwise distributing your application code, you may find that it is difficult to manage the differences between accounts. For instance, in different accounts on different machines Webware may be installed in different locations. You may have the actual directory in a different location as well -- it may be in ~/webware/WorkingDir for your active development, but /var/webware/WorkingDir for the production version. And if there are multiple development copies on the same machine, you have to be sure they each use different adapter ports.
To solve these problems I recommend creating a shell script to handle startup. I generally call this script start, and it looks something like this:
#!/bin/sh # lothlorien.colorstudy.com is my development machine if [ `hostname` = lothlorien.colorstudy.com ] ; then WORKING=$HOME/prog/webware/WorkingDir WEBWARE=$HOME/prog/webware/Webware OPS="--AppServer.AutoReload=1" fi # this is my production environment if [ `hostname` = color.colorstudy.com && `whoami` = webware ] ; then WORKING=/www/WorkingDir WEBWARE=/www/Webware OPS="" fi if [ "$WORKING" = "" ] ; then echo I do not recognize this environment exit 1 fi cd $WORKING ./AppServer --working-path=$WORKING --webware-path=$WEBWARE $OPS $*
You can add this to CVS, and the script should automatically detect what environment it is being used in. You can use options to change configuration parameters, like setting some parameters depending on whether the environment is a development or production environment. (@@ ib: add link to command line options)
Some options that you may be particularly interested in:
For more settings, see the Configuration document.
Once you've got the basic files and directories in place, you're ready to go in and write some code. Don't let this document get in the way of developing the application how you choose, but here are some common patterns that have proven useful for Webware applications.
Subclass WebKit.Page for your application. This subclass will change some methods and add some new methods. It serves as the basis of all the pages that follow.
Some code you may wish to include in your SitePage:
I also typically add other functions to the SitePage module, and then do from lib.SitePage import * in each servlet -- this might include functions like htmlEncode, or some other select functions that I use constantly in web applications. Whether you want to use functions or methods is up to you -- in many cases methods can be more easily extended or customized later, but sometimes method use can become excessive and create unnecessary dependences in your code.
A basic framework for your SitePage might be:
from WebKit.Page import Page class SitePage(Page): def respond(self, trans): if self.securePage(): if not self.session().value('username', False): self.respondLogIn() return def securePage(self): """Override this method in your servlets to return True if the page should only be accessible to logged-in users -- by default pages are publically viewable""" return False def respondLogin(self): # Here we should deal with logging in... pass
Obviously there are a lot of details to add in on your own which are specific to your application and the security and user model you are using.