Author: chrisz
Date: Wed Sep 28 02:07:11 2005
New Revision: 3327
Modified:
Webware/trunk/WebKit/Docs/ApplicationDevelopment.html
Webware/trunk/WebKit/Docs/ApplicationDevelopment.txt
Webware/trunk/WebKit/Docs/Configuration.html
Webware/trunk/WebKit/Docs/Developing.html
Webware/trunk/WebKit/Docs/InstallGuide.html
Webware/trunk/WebKit/Docs/Tutorial.html
Webware/trunk/WebKit/Docs/Tutorial.txt
Webware/trunk/WebKit/Docs/UsersGuide.html
Log:
Addition to AppDevelopment; recreated the html with docutils.
Modified: Webware/trunk/WebKit/Docs/ApplicationDevelopment.html
==============================================================================
--- Webware/trunk/WebKit/Docs/ApplicationDevelopment.html (original)
+++ Webware/trunk/WebKit/Docs/ApplicationDevelopment.html Wed Sep 28 02:07:11 2005
@@ -9,7 +9,7 @@
</head>
<body>
<div class="document" id="application-development-with-webware">
-<h1 class="header">Application Development With Webware</h1>
+<h1 class="title">Application Development With Webware</h1>
<p>Webware for Python</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
@@ -27,7 +27,7 @@
<li><a class="reference" href="#synopsis" id="id2" name="id2">Synopsis</a></li>
<li><a class="reference" href="#setting-up-your-application" id="id3" name="id3">Setting up your application</a><ul>
<li><a class="reference" href="#creating-a-working-directory" id="id4" name="id4">Creating a Working Directory</a></li>
-<li><a class="reference" href="#using-cvs-for-your-application" id="id5" name="id5">Using CVS for your application</a></li>
+<li><a class="reference" href="#using-a-version-control-system-for-your-application" id="id5" name="id5">Using a version control system for your application</a></li>
<li><a class="reference" href="#using-the-working-directory-from-multiple-accounts" id="id6" name="id6">Using the working directory from multiple accounts</a></li>
</ul>
</li>
@@ -43,33 +43,46 @@
</div>
<div class="section" id="setting-up-your-application">
<h1><a class="toc-backref" href="#id3" name="setting-up-your-application">Setting up your application</a></h1>
-<p>The first task in developing an application is to set up the file structure in which you will be working.</p>
-<p>It is possible to put your application in a subdirectory under <tt class="docutils literal"><span class="pre">WebKit/</span></tt> and change <tt class="docutils literal"><span class="pre">WebKit/Configs/Application.config</span></tt> to add another context. But <em>do not do this</em>. 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.</p>
+<p>The first task in developing an application is to set up the file structure in
+which you will be working.</p>
+<p>It is possible to put your application in a subdirectory under <tt class="docutils literal"><span class="pre">WebKit/</span></tt> and
+change <tt class="docutils literal"><span class="pre">WebKit/Configs/Application.config</span></tt> to add another context.
+But <em>do not do this</em>. 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.</p>
<div class="section" id="creating-a-working-directory">
<h2><a class="toc-backref" href="#id4" name="creating-a-working-directory">Creating a Working Directory</a></h2>
-<p>Instead you should use the script <tt class="docutils literal"><span class="pre">bin/MakeAppWorkDir.py</span></tt>. You should run it like:</p>
+<p>Instead you should use the script <tt class="docutils literal"><span class="pre">bin/MakeAppWorkDir.py</span></tt>.
+You should run it like:</p>
<pre class="literal-block">
-$ python Webware/bin/MakeAppWorkDir -l --cvsignore -c context DIRECTORYNAME
+$ python Webware/bin/MakeAppWorkDir -c Context -l Lib --cvsignore WorkDir
</pre>
-<p>This will create a directory DIRECTORYNAME that will contain a directory structure for your application. The options are:</p>
+<p>This will create a directory <tt class="docutils literal"><span class="pre">WorkDir</span></tt> that will contain a directory structure
+for your application. The options are:</p>
<dl class="docutils">
-<dt><tt class="docutils literal"><span class="pre">-l</span></tt>:</dt>
-<dd>Create a <tt class="docutils literal"><span class="pre">lib/</span></tt> directory which will be added to the Python path.</dd>
+<dt><tt class="docutils literal"><span class="pre">-c</span> <span class="pre">Context</span></tt>:</dt>
+<dd>Use <tt class="docutils literal"><span class="pre">Context</span></tt> as the name for the application default context.
+A subdirectory with the same name will be created in the work dir (you can
+change that with the <tt class="docutils literal"><span class="pre">-d</span></tt> option).
+If you do not use the <tt class="docutils literal"><span class="pre">-c</span></tt> option, the context name will be <tt class="docutils literal"><span class="pre">MyContext</span></tt>.
+I like the name <tt class="docutils literal"><span class="pre">Context</span></tt> for all my applications.</dd>
+<dt><tt class="docutils literal"><span class="pre">-l</span> <span class="pre">Lib</span></tt>:</dt>
+<dd>Create a <tt class="docutils literal"><span class="pre">Lib</span></tt> directory in the work dir which will be added to the Python
+path. You can use the <tt class="docutils literal"><span class="pre">-l</span></tt> option multiple times; and you can also add
+already existent library directories outside of the work dir.</dd>
<dt><tt class="docutils literal"><span class="pre">--cvsignore</span></tt>:</dt>
-<dd>Create <tt class="docutils literal"><span class="pre">.cvsignore</span></tt> files.</dd>
-<dt><tt class="docutils literal"><span class="pre">-c</span> <span class="pre">CONTEXTNAME</span></tt>:</dt>
-<dd>Use CONTEXTNAME for the application context instead of <tt class="docutils literal"><span class="pre">MyContext</span></tt> (there
-will be a directory CONTEXTNAME/ in the work dir). I like the name
-<tt class="docutils literal"><span class="pre">context</span></tt> for all my applications.</dd>
-<dt><tt class="docutils literal"><span class="pre">DIRECTORYNAME</span></tt>:</dt>
-<dd>The files will be put here. Name if after your application, place it where
+<dd>Create <tt class="docutils literal"><span class="pre">.cvsignore</span></tt> files for use with CVS.</dd>
+<dt><tt class="docutils literal"><span class="pre">WorkDir</span></tt>:</dt>
+<dd>The files will be put here. Name if after your application, place it where
it is convenient for you -- it doesn't need to be located close to the
Webware installation.</dd>
</dl>
+<p>You can see all available options if you run <tt class="docutils literal"><span class="pre">Webware/bin/MakeAppWorkDir.py</span></tt>
+without any parameters.</p>
<p>When you do this, you'll see this directory structure:</p>
<pre class="literal-block">
-404Text.txt Cache/ ErrorMsgs/ Logs/ WebKit.cgi lib/
-AppServer* Configs/ Launch.py Sessions/ context/
+404Text.txt Cache/ ErrorMsgs/ Logs/ WebKit.cgi Lib/
+AppServer* Configs/ Launch.py Sessions/ Context/
</pre>
<p>Here's what the files and directories are for:</p>
<dl class="docutils">
@@ -77,51 +90,99 @@
<dd>The text when a page is not found (actually the HTML from <body> to
</body>).</dd>
<dt><tt class="docutils literal"><span class="pre">AppServer</span></tt>:</dt>
-<dd>The script to start up the AppServer for this application. Each application
-will have its own AppServer, and its own process.</dd>
+<dd>The script to start up the AppServer for this application.
+Each application will have its own AppServer, and its own process.
+If you are running under Windows, you will see a <tt class="docutils literal"><span class="pre">AppServer.bat</span></tt>
+instead and additionally, you will find a <tt class="docutils literal"><span class="pre">AppServerService.py</span></tt>
+script that can be used to start the AppServer as a service.</dd>
<dt><tt class="docutils literal"><span class="pre">Cache</span></tt>:</dt>
-<dd>A directory containing cache files. You won't need to look in here.</dd>
+<dd>A directory containing cache files. You won't need to look in here.</dd>
<dt><tt class="docutils literal"><span class="pre">Configs</span></tt>:</dt>
-<dd>Configuration files for the application. These files are taken from
+<dd>Configuration files for the application. These files are copied from
<tt class="docutils literal"><span class="pre">WebKit/Configs</span></tt>, but are specific to this application/AppServer.</dd>
<dt><tt class="docutils literal"><span class="pre">ErrorMsgs</span></tt>:</dt>
-<dd>HTML pages for any errors that occur. These can pile up and take up
-considerable size (even just during development), so you'll want to purge
-these every so often.</dd>
+<dd>HTML pages for any errors that occur. These can pile up and take up
+considerable size (even just during development), so you'll want to
+purge these every so often.</dd>
<dt><tt class="docutils literal"><span class="pre">Launch.py</span></tt>:</dt>
<dd>Called by the <tt class="docutils literal"><span class="pre">AppServer</span></tt> script to launch the AppServer.</dd>
<dt><tt class="docutils literal"><span class="pre">Logs</span></tt>:</dt>
<dd>Logs of accesses.</dd>
<dt><tt class="docutils literal"><span class="pre">Sessions</span></tt>:</dt>
-<dd>Users sessions. These should be cleaned out automatically, you won't
+<dd>Users sessions. These should be cleaned out automatically, you won't
have to look in this directory.</dd>
<dt><tt class="docutils literal"><span class="pre">WebKit.cgi</span></tt>:</dt>
-<dd>A CGI script/adapter for accessing the AppServer here. You can still use
+<dd>A CGI script/adapter for accessing the AppServer here. You can still use
the other adapters, but most of them don't need to be configured for the
-individual applications. I still recommend mod_webkit or wkcgi.</dd>
-<dt><tt class="docutils literal"><span class="pre">context</span></tt>:</dt>
-<dd>The directory (given with the <tt class="docutils literal"><span class="pre">-c</span></tt> switch) for your default context. This
-is where you put your servlets.</dd>
-<dt><tt class="docutils literal"><span class="pre">lib</span></tt>:</dt>
-<dd>An application-specific library package, created if you give the <tt class="docutils literal"><span class="pre">-l</span></tt>
-switch. Import from this like <tt class="docutils literal"><span class="pre">from</span> <span class="pre">lib.SitePage</span> <span class="pre">import</span> <span class="pre">SitePage</span></tt></dd>
+individual applications. I still recommend <tt class="docutils literal"><span class="pre">mod_webkit</span></tt> or <tt class="docutils literal"><span class="pre">wkcgi</span></tt>.</dd>
+<dt><tt class="docutils literal"><span class="pre">Context</span></tt>:</dt>
+<dd>The directory for your default context. This is where you put your servlets.
+you can change its name and location with the <tt class="docutils literal"><span class="pre">`-c</span></tt> and <tt class="docutils literal"><span class="pre">-d</span></tt> options.
+You can also change this subsequently in the <tt class="docutils literal"><span class="pre">Application.config</span></tt> file
+in the <tt class="docutils literal"><span class="pre">Configs</span></tt> directory, where you can also configure more than one
+context. You may also want to remove the other standard contexts that come
+with Webware from the config file.</dd>
+<dt><tt class="docutils literal"><span class="pre">Lib</span></tt>:</dt>
+<dd>An example for an application-specific library package that can be created
+<tt class="docutils literal"><span class="pre">-l</span></tt> option (in this case, <tt class="docutils literal"><span class="pre">-l</span> <span class="pre">Lib</span></tt>. Import modules from this directory
+like <tt class="docutils literal"><span class="pre">from</span> <span class="pre">Lib.SitePage</span> <span class="pre">import</span> <span class="pre">SitePage</span></tt>.</dd>
</dl>
</div>
-<div class="section" id="using-cvs-for-your-application">
-<h2><a class="toc-backref" href="#id5" name="using-cvs-for-your-application">Using CVS for your application</a></h2>
-<p>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.</p>
-<p>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:</p>
-<pre class="literal-block">
-$ cd WorkingDir
-$ cvs import -d 'initial import' WorkingDir ianb start
-@@ ib: check this command
+<div class="section" id="using-a-version-control-system-for-your-application">
+<h2><a class="toc-backref" href="#id5" name="using-a-version-control-system-for-your-application">Using a version control system for your application</a></h2>
+<p>A version control system is a useful tool for managing your application. Popular
+Open Source version control systems are are the Concurrent Versions System (CVS)
+and, increasingly, Subversion (SVN). I recommend using SVN because it has a few
+advantages over CVS. For instance, it tracks both files and directories and
+handles copy, rename, and delete operations on files well. These systems handle
+versioning, but they also make it possible for other people to see snapshots of
+your progress, for multiple developers to collaborate and work on an application
+simultaneously, and they create a sort of implicit file share for your project.
+Even if you are the only developer on an application, a version control system
+can be very helpful.</p>
+<p>The working directory is a good place to start for creating a versioned project.
+Assuming you've set up CVS, and set CVSROOT to point to your repository, you can
+get started by importing your project into the repository simply by running:</p>
+<pre class="literal-block">
+$ cd WorkDir
+$ cvs import -m 'initial import' MyWebwareProject username start
+</pre>
+<p>Replace <tt class="docutils literal"><span class="pre">MyWebwareProject</span></tt> with the name of your project and <tt class="docutils literal"><span class="pre">username</span></tt> with
+your own user name. You should use the option <tt class="docutils literal"><span class="pre">--cvsignore</span></tt> when running
+<tt class="docutils literal"><span class="pre">MakeAppWorkDir.py</span></tt> if you plan to do this. If you do, then <tt class="docutils literal"><span class="pre">.cvsignore</span></tt>
+files will be added to each directory. These tell CVS to ignore files with
+certain extensions (such as <tt class="docutils literal"><span class="pre">.pyc</span></tt> files), and all the files in certain
+directories (<tt class="docutils literal"><span class="pre">Cache</span></tt>, <tt class="docutils literal"><span class="pre">ErrorMsgs</span></tt>, <tt class="docutils literal"><span class="pre">Logs</span></tt>, and <tt class="docutils literal"><span class="pre">Sessions</span></tt>).
+You shouldn't otherwise notice these files, even if you aren't using CVS.</p>
+<p>The command to import your project into a SVN repository is very similar:</p>
+<pre class="literal-block">
+$ cd WorkDir
+$ svn import -m 'initial import' https://myserver/myrepos/MyWebWareProject
</pre>
-<p>You should use <tt class="docutils literal"><span class="pre">--cvsignore</span></tt> if you plan to do this. If you do then <tt class="docutils literal"><span class="pre">.cvsignore</span></tt> files will be added to each directory. These tell <tt class="docutils literal"><span class="pre">cvs</span></tt> to ignore certain files -- <tt class="docutils literal"><span class="pre">.pyc</span></tt> files, and all the files in certain directories (<tt class="docutils literal"><span class="pre">Cache</span></tt>, <tt class="docutils literal"><span class="pre">ErrorMsgs</span></tt>, <tt class="docutils literal"><span class="pre">Logs</span></tt>, and <tt class="docutils literal"><span class="pre">Sessions</span></tt>). You shouldn't otherwise notice these files, even if you aren't using CVS.</p>
+<p>Replace <tt class="docutils literal"><span class="pre">https://myserver/myrepos/</span></tt> with the URL of your SVN repository. The
+<tt class="docutils literal"><span class="pre">.cvsignore</span></tt> files will not be used in this case. Instead, you have to set the
+<tt class="docutils literal"><span class="pre">svn:ignore</span></tt> property on the respective directory. You can still use the
+<tt class="docutils literal"><span class="pre">.cvsignore</span></tt> files to generate the necessary <tt class="docutils literal"><span class="pre">svn</span> <span class="pre">propset</span></tt> commands:</p>
+<pre class="literal-block">
+$ find . -name .cvsignore | while read f; \
+> do echo svn propset svn:ignore -F $f $(dirname $f); done
+</pre>
+<p>After importing <tt class="docutils literal"><span class="pre">WorkDir</span></tt> to the repository, note that it is not automatically
+under version control. To start working, you first need to explicitely check it
+out from the repository using <tt class="docutils literal"><span class="pre">cvs</span> <span class="pre">checkout</span></tt> or <tt class="docutils literal"><span class="pre">svn</span> <span class="pre">checkout</span></tt>.</p>
</div>
<div class="section" id="using-the-working-directory-from-multiple-accounts">
<h2><a class="toc-backref" href="#id6" name="using-the-working-directory-from-multiple-accounts">Using the working directory from multiple accounts</a></h2>
-<p>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 <tt class="docutils literal"><span class="pre">~/webware/WorkingDir</span></tt> for your active development, but <tt class="docutils literal"><span class="pre">/var/webware/WorkingDir</span></tt> 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.</p>
-<p>To solve these problems I recommend creating a shell script to handle startup. I generally call this script <tt class="docutils literal"><span class="pre">start</span></tt>, and it looks something like this:</p>
+<p>If you are using a version control system or if you are 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
+<tt class="docutils literal"><span class="pre">~/webware/WorkDir</span></tt> for your active development, but <tt class="docutils literal"><span class="pre">/var/webware/WorkDir</span></tt>
+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.</p>
+<p>To solve these problems I recommend creating a shell script to handle startup.
+I generally call this script <tt class="docutils literal"><span class="pre">start</span></tt>, and it looks something like this:</p>
<pre class="literal-block">
#!/bin/sh
@@ -145,9 +206,12 @@
fi
cd $WORKING
-./AppServer --working-path=$WORKING --webware-path=$WEBWARE $OPS $*
+./AppServer --work-dir=$WORKING --webware-dir=$WEBWARE $OPS $*
</pre>
-<p>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)</p>
+<p>You can add this to your project in the repository, 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.</p>
<p>Some options that you may be particularly interested in:</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">--AppServer.AutoReload</span></tt>:</dt>
@@ -169,18 +233,30 @@
</div>
<div class="section" id="structuring-your-code">
<h1><a class="toc-backref" href="#id7" name="structuring-your-code">Structuring your Code</a></h1>
-<p>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.</p>
+<p>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.</p>
<div class="section" id="sitepage">
<h2><a class="toc-backref" href="#id8" name="sitepage">SitePage</a></h2>
-<p>Subclass <tt class="docutils literal"><span class="pre">WebKit.Page</span></tt> 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.</p>
-<p>Some code you may wish to include in your SitePage:</p>
+<p>Subclass a <tt class="docutils literal"><span class="pre">SitePage</span></tt> from <tt class="docutils literal"><span class="pre">WebKit.Page</span></tt> for your application. This subclass
+will change some methods and add some new methods. It serves as the basis and
+as a template for all the pages that follow.</p>
+<p>Some code you may wish to include in your <tt class="docutils literal"><span class="pre">SitePage</span></tt>:</p>
<ul class="simple">
<li>Authentication and security</li>
<li>Accessing common objects (e.g., a user object, or a document object)</li>
<li>Page header and footer</li>
<li>Common layout commands, like <tt class="docutils literal"><span class="pre">writeHeader</span></tt></li>
+<li>Database access</li>
</ul>
-<p>I also typically add other functions to the SitePage module, and then do <tt class="docutils literal"><span class="pre">from</span> <span class="pre">lib.SitePage</span> <span class="pre">import</span> <span class="pre">*</span></tt> 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.</p>
+<p>I also typically add other functions to the SitePage module, and then do
+<tt class="docutils literal"><span class="pre">from</span> <span class="pre">Lib.SitePage</span> <span class="pre">import</span> <span class="pre">*</span></tt> 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.</p>
<p>A basic framework for your SitePage might be:</p>
<pre class="literal-block">
from WebKit.Page import Page
@@ -203,12 +279,10 @@
# Here we should deal with logging in...
pass
</pre>
-<p>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.</p>
-</div>
+<p>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.</p>
</div>
</div>
-<div class="footer">
-Webware for Python (<a href="http://www.webwareforpython.org">www.webwareforpython.org</a>)
</div>
</body>
</html>
Modified: Webware/trunk/WebKit/Docs/ApplicationDevelopment.txt
==============================================================================
--- Webware/trunk/WebKit/Docs/ApplicationDevelopment.txt (original)
+++ Webware/trunk/WebKit/Docs/ApplicationDevelopment.txt Wed Sep 28 02:07:11 2005
@@ -127,7 +127,7 @@
Replace ``MyWebwareProject`` with the name of your project and ``username`` with
your own user name. You should use the option ``--cvsignore`` when running
-``MakeAppWorkDir.py`` if you plan to do this. If you do then ``.cvsignore``
+``MakeAppWorkDir.py`` if you plan to do this. If you do, then ``.cvsignore``
files will be added to each directory. These tell CVS to ignore files with
certain extensions (such as ``.pyc`` files), and all the files in certain
directories (``Cache``, ``ErrorMsgs``, ``Logs``, and ``Sessions``).
@@ -138,7 +138,13 @@
$ cd WorkDir
$ svn import -m 'initial import' https://myserver/myrepos/MyWebWareProject
-Replace ``https://myserver/myrepos/`` with the URL of your SVN repository.
+Replace ``https://myserver/myrepos/`` with the URL of your SVN repository. The
+``.cvsignore`` files will not be used in this case. Instead, you have to set the
+``svn:ignore`` property on the respective directory. You can still use the
+``.cvsignore`` files to generate the necessary ``svn propset`` commands::
+
+ $ find . -name .cvsignore | while read f; \
+ > do echo svn propset svn:ignore -F $f $(dirname $f); done
After importing ``WorkDir`` to the repository, note that it is not automatically
under version control. To start working, you first need to explicitely check it
Modified: Webware/trunk/WebKit/Docs/Configuration.html
==============================================================================
--- Webware/trunk/WebKit/Docs/Configuration.html (original)
+++ Webware/trunk/WebKit/Docs/Configuration.html Wed Sep 28 02:07:11 2005
@@ -9,7 +9,7 @@
</head>
<body>
<div class="document" id="configuration-guide">
-<h1 class="header">Configuration Guide</h1>
+<h1 class="title">Configuration Guide</h1>
<div class="contents topic" id="contents">
<p class="topic-title first"><a name="contents">Contents</a></p>
<ul class="simple">
@@ -421,8 +421,5 @@
</dl>
</div>
</div>
-<div class="footer">
-Webware for Python (<a href="http://www.webwareforpython.org">www.webwareforpython.org</a>)
-</div>
</body>
</html>
Modified: Webware/trunk/WebKit/Docs/Developing.html
==============================================================================
--- Webware/trunk/WebKit/Docs/Developing.html (original)
+++ Webware/trunk/WebKit/Docs/Developing.html Wed Sep 28 02:07:11 2005
@@ -9,7 +9,7 @@
</head>
<body>
<div class="document" id="developing-webware">
-<h1 class="header">Developing Webware</h1>
+<h1 class="title">Developing Webware</h1>
<p>This document should outline the details you need to understand
Webware and WebKit internals, and assist in becoming a more advanced
Webware programmer.</p>
@@ -60,8 +60,5 @@
<p>A plugin who's <tt class="docutils literal"><span class="pre">requiredPyVersion</span></tt> or <tt class="docutils literal"><span class="pre">requiredOpSys</span></tt> aren't satisfied will simply be ignored. <tt class="docutils literal"><span class="pre">requiredOpSys</span></tt> should be something returned by <tt class="docutils literal"><span class="pre">os.name</span></tt>, like <tt class="docutils literal"><span class="pre">posix</span></tt> or <tt class="docutils literal"><span class="pre">nt</span></tt>. Or you can define a function <tt class="docutils literal"><span class="pre">willRunFunc</span></tt> to test. If there aren't requirements you can leave these variables and functions out.</p>
</div>
</div>
-<div class="footer">
-Webware for Python (<a href="http://www.webwareforpython.org">www.webwareforpython.org</a>)
-</div>
</body>
</html>
Modified: Webware/trunk/WebKit/Docs/InstallGuide.html
==============================================================================
--- Webware/trunk/WebKit/Docs/InstallGuide.html (original)
+++ Webware/trunk/WebKit/Docs/InstallGuide.html Wed Sep 28 02:07:11 2005
@@ -9,7 +9,7 @@
</head>
<body>
<div class="document" id="webkit-install-guide">
-<h1 class="header">WebKit Install Guide</h1>
+<h1 class="title">WebKit Install Guide</h1>
<div class="contents topic" id="contents">
<p class="topic-title first"><a name="contents">Contents</a></p>
<ul class="simple">
@@ -767,7 +767,7 @@
<dt><tt class="docutils literal"><span class="pre">WebKit.cgi</span></tt>:</dt>
<dd>A CGI script/adapter for accessing the AppServer here. You can still use
the other adapters, but most of them don't need to be configured for the
-individual applications. I still recommend mod_webkit or wkcgi.</dd>
+individual applications. I still recommend <tt class="docutils literal"><span class="pre">mod_webkit</span></tt> or <tt class="docutils literal"><span class="pre">wkcgi</span></tt>.</dd>
<dt><tt class="docutils literal"><span class="pre">MyContext</span></tt>:</dt>
<dd>The directory for your default context. This is where you put your servlets.
you can change its name and location with the <tt class="docutils literal"><span class="pre">`-c</span></tt> and <tt class="docutils literal"><span class="pre">-d</span></tt> options.
@@ -778,7 +778,7 @@
<dt><tt class="docutils literal"><span class="pre">Lib</span></tt>:</dt>
<dd>An example for an application-specific library package that can be created
<tt class="docutils literal"><span class="pre">-l</span></tt> option (in this case, <tt class="docutils literal"><span class="pre">-l</span> <span class="pre">Lib</span></tt>. Import modules from this directory
-like <tt class="docutils literal"><span class="pre">from</span> <span class="pre">lib.SitePage</span> <span class="pre">import</span> <span class="pre">SitePage</span></tt>.</dd>
+like <tt class="docutils literal"><span class="pre">from</span> <span class="pre">Lib.SitePage</span> <span class="pre">import</span> <span class="pre">SitePage</span></tt>.</dd>
</dl>
</div>
</div>
@@ -982,8 +982,5 @@
</div>
</div>
</div>
-<div class="footer">
-Webware for Python (<a href="http://www.webwareforpython.org">www.webwareforpython.org</a>)
-</div>
</body>
</html>
Modified: Webware/trunk/WebKit/Docs/Tutorial.html
==============================================================================
--- Webware/trunk/WebKit/Docs/Tutorial.html (original)
+++ Webware/trunk/WebKit/Docs/Tutorial.html Wed Sep 28 02:07:11 2005
@@ -9,7 +9,7 @@
</head>
<body>
<div class="document" id="beginner-tutorial">
-<h1 class="header">Beginner Tutorial</h1>
+<h1 class="title">Beginner Tutorial</h1>
<p>Webware for Python</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
@@ -42,56 +42,85 @@
</div>
<div class="section" id="synopsis">
<h1><a class="toc-backref" href="#id6" name="synopsis">Synopsis</a></h1>
-<p>We present a tutorial on making a Webware script, and some guidance on turning that into a web application.</p>
+<p>We present a tutorial on making a Webware script, and some guidance on turning
+that into a web application.</p>
</div>
<div class="section" id="installation">
<h1><a class="toc-backref" href="#id7" name="installation">Installation</a></h1>
-<p>This document does not cover the basic installation. See the <a class="reference" href="InstallGuide.html">Install Guide</a>
--- you should be able to open up the Examples context in Webware before you continue.</p>
+<p>This document does not cover the basic installation. See the <a class="reference" href="InstallGuide.html">Install Guide</a>
+-- you should be able to open up the WebKit Examples context in you browser
+before you continue. For the beginning, you can use the built-in HTTP server,
+but in a production environment you should use a real web server like Apache.</p>
</div>
<div class="section" id="setting-up-your-environment">
<h1><a class="toc-backref" href="#id8" name="setting-up-your-environment">Setting Up Your Environment</a></h1>
<div class="section" id="creating-a-working-directory">
<h2><a class="toc-backref" href="#id9" name="creating-a-working-directory">Creating a Working Directory</a></h2>
-<p>We'll first set up a directory dedicated to your application. Run this command:</p>
+<p>We'll first set up a directory dedicated to your application. Run this command:</p>
<pre class="literal-block">
$ cd ~
-$ python /path/to/Webware/bin/MakeAppWorkDir.py -l --cvsignore \
- -c context WebwareTest
+$ python /path/to/Webware/bin/MakeAppWorkDir.py -c Context -l Lib \
+ --cvsignore WebwareTest
</pre>
-<p>You'll now have a directory WebwareTest in your home directory (or of course you can put it in some other location). Inside this directory will be several subdirectories and a couple files. The only file we'll worry about is <tt class="docutils literal"><span class="pre">AppServer</span></tt> (or <tt class="docutils literal"><span class="pre">AppServer.bat</span></tt> if you're on Windows). The directories of interest are <tt class="docutils literal"><span class="pre">context</span></tt> (that you specified with <tt class="docutils literal"><span class="pre">-c</span> <span class="pre">context</span></tt>) where you'll be putting your servlets; <tt class="docutils literal"><span class="pre">Configs</span></tt> that holds some configuration files; and <tt class="docutils literal"><span class="pre">lib</span></tt> where you can put your non-servlet code.</p>
-<p>For more information about the working directory and setting up the file structure for your application, see <a class="reference" href="ApplicationDevelopment.html">Application Development</a>.</p>
+<p>You'll now have a directory WebwareTest in your home directory (or of course
+you can put it in some other location). Inside this directory will be several
+subdirectories and a couple files. The only file we'll worry about is
+<tt class="docutils literal"><span class="pre">AppServer</span></tt> (or <tt class="docutils literal"><span class="pre">AppServer.bat</span></tt> if you're on Windows). The directories of
+interest are <tt class="docutils literal"><span class="pre">Context</span></tt> (that you specified with <tt class="docutils literal"><span class="pre">-C</span> <span class="pre">context</span></tt>) where you'll
+be putting your servlets; <tt class="docutils literal"><span class="pre">Configs</span></tt> that holds some configuration files;
+and <tt class="docutils literal"><span class="pre">Lib</span></tt> where you can put your non-servlet code.</p>
+<p>For more information about the working directory and setting up the file
+structure for your application, see <a class="reference" href="ApplicationDevelopment.html">Application Development</a>.</p>
</div>
<div class="section" id="changing-webware-configuration">
<h2><a class="toc-backref" href="#id10" name="changing-webware-configuration">Changing Webware Configuration</a></h2>
-<p>For the most part the configuration is fine, but we'll make a couple changes to make it easier to develop. For more information on configuration see the <a class="reference" href="Configuration.html">Configuration Guide</a>.</p>
+<p>For the most part the configuration is fine, but we'll make a couple changes to
+make it easier to develop. For more information on configuration see the
+<a class="reference" href="Configuration.html">Configuration Guide</a>.</p>
<p>In the file <tt class="docutils literal"><span class="pre">AppServer.config</span></tt>, change this line:</p>
<pre class="literal-block">
# Original (default setting):
- 'AutoReload': 0,
+ AutoReload = False
# To:
- 'AutoReload': 1,
+ AutoReload = True
</pre>
-<p>This will cause the AppServer to restart if any loaded files are changed -- without this you may edit a file and your application won't see the updated version until you manually restart the AppServer.</p>
-<p>The other change you may want to make to allow you to use more interesting URLs. In Application.config:</p>
+<p>This will cause the AppServer to restart if any loaded files are changed --
+without this you may edit a file and your application won't see the updated
+version until you manually restart the AppServer.</p>
+<p>The other change you may want to make to allow you to use more interesting URLs.
+In Application.config:</p>
<pre class="literal-block">
# Original (default setting):
- 'ExtraPathInfo': 0,
+ ExtraPathInfo = False
# To:
- 'ExtraPathInfo': 1,
+ ExtraPathInfo = True
</pre>
-<p>Otherwise the settings should be appropriate for development. (There are several you would want to change before deploying the application in a production environment).</p>
+<p>Otherwise the settings should be appropriate for development.
+(There are several setting you would want to change before deploying the
+application in a production environment).</p>
</div>
</div>
<div class="section" id="creating-and-understanding-the-servlet">
<h1><a class="toc-backref" href="#id11" name="creating-and-understanding-the-servlet">Creating and Understanding the Servlet</a></h1>
-<p>Webware's core concept for serving pages is the <em>servlet</em>. This is a class that creates a response given a request.</p>
-<p>The core classes to understanding the servlet are <tt class="docutils literal"><span class="pre">Servlet</span></tt>, <tt class="docutils literal"><span class="pre">HTTPServlet</span></tt>, and <tt class="docutils literal"><span class="pre">Page</span></tt>. Also of interest would be the request (<tt class="docutils literal"><span class="pre">Request</span></tt> and <tt class="docutils literal"><span class="pre">HTTPRequest</span></tt>) and the response (<tt class="docutils literal"><span class="pre">Response</span></tt> and <tt class="docutils literal"><span class="pre">HTTPResponse</span></tt>) -- the <tt class="docutils literal"><span class="pre">HTTP-</span></tt> versions of these classes are more interesting. There is also a <tt class="docutils literal"><span class="pre">Transaction</span></tt> object, which is solely a container for the request and response.</p>
-<p>While there are several levels you can work on while creating your servlet, in this tutorial we will work solely with subclassing the <tt class="docutils literal"><span class="pre">Page</span></tt> class. This class defines a more high-level interface, appropriate for generating HTML (though it can be used with any content type). It also provides a number of convenience methods.</p>
+<p>Webware's core concept for serving pages is the <em>servlet</em>. This is a class that
+creates a response given a request.</p>
+<p>The core classes to understanding the servlet are <tt class="docutils literal"><span class="pre">Servlet</span></tt>, <tt class="docutils literal"><span class="pre">HTTPServlet</span></tt>,
+and <tt class="docutils literal"><span class="pre">Page</span></tt>. Also of interest would be the request (<tt class="docutils literal"><span class="pre">Request</span></tt> and
+<tt class="docutils literal"><span class="pre">HTTPRequest</span></tt>) and the response (<tt class="docutils literal"><span class="pre">Response</span></tt> and <tt class="docutils literal"><span class="pre">HTTPResponse</span></tt>)
+-- the <tt class="docutils literal"><span class="pre">HTTP-</span></tt> versions of these classes are more interesting.
+There is also a <tt class="docutils literal"><span class="pre">Transaction</span></tt> object, which is solely a container for the
+request and response.</p>
+<p>While there are several levels you can work on while creating your servlet,
+in this tutorial we will work solely with subclassing the <tt class="docutils literal"><span class="pre">Page</span></tt> class.
+This class defines a more high-level interface, appropriate for generating HTML
+(though it can be used with any content type). It also provides a number of
+convenience methods.</p>
</div>
<div class="section" id="a-brief-introduction-to-the-servlet">
<h1><a class="toc-backref" href="#id12" name="a-brief-introduction-to-the-servlet">A Brief Introduction to the Servlet</a></h1>
-<p>Each servlet is a plain Python class. There is no Webware magic (except perhaps for the level one <em>import module based on URL</em> spell). <a class="reference" href="../../PSP/Docs/index.html">PSP</a> has more magic, but that's a topic for another day.</p>
+<p>Each servlet is a plain Python class. There is no Webware magic (except perhaps
+for the level one <em>import module based on URL</em> spell). <a class="reference" href="../../PSP/Docs/index.html">PSP</a> has more magic,
+but that's a topic for another day.</p>
<p>An extremely simple servlet might look like:</p>
<pre class="literal-block">
from WebKit.Page import Page
@@ -104,89 +133,109 @@
def writeContent(self):
self.write('Hello world!')
</pre>
-<p>This would be placed in <tt class="docutils literal"><span class="pre">MyServlet.py</span></tt>. Webware will create a pool of <tt class="docutils literal"><span class="pre">MyServlet</span></tt> instances, which will be reused. Servlets "write" the text of the response (like <tt class="docutils literal"><span class="pre">self.write("some</span> <span class="pre">text")</span></tt>). Webware calls the servlet like this:</p>
+<p>This would be placed in <tt class="docutils literal"><span class="pre">MyServlet.py</span></tt>.
+Webware will create a pool of <tt class="docutils literal"><span class="pre">MyServlet</span></tt> instances, which will be reused.
+Servlets "write" the text of the response (like <tt class="docutils literal"><span class="pre">self.write("some</span> <span class="pre">text")</span></tt>).
+Webware calls the servlet like this:</p>
<ul class="simple">
<li>An unused servlet is taken from the pool, or another servlet is created.</li>
-<li><tt class="docutils literal"><span class="pre">awake(transaction)</span></tt> is called. This is a good place to set up data
-for your servlet. You can put information in instance variables for use later
-on. But be warned -- those instance variables will hang around potentially
+<li><tt class="docutils literal"><span class="pre">awake(transaction)</span></tt> is called. This is a good place to set up data for
+your servlet. ou can put information in instance variables for use later
+on. But be warned -- those instance variables will hang around potentially
for a long time if you don't delete them later (in <tt class="docutils literal"><span class="pre">sleep</span></tt>).</li>
-<li>Several low-level methods are called, which Page isolates you from. We will
+<li>Several low-level methods are called, which Page isolates you from. We will
ignore these.</li>
-<li><tt class="docutils literal"><span class="pre">writeHTML()</span></tt> is called. <tt class="docutils literal"><span class="pre">Page</span></tt> implements this just fine, but you
-can override it if you want total control, or if you want to output something
+<li><tt class="docutils literal"><span class="pre">writeHTML()</span></tt> is called. <tt class="docutils literal"><span class="pre">Page</span></tt> implements this just fine, but you can
+override it if you want total control, or if you want to output something
other than HTML.</li>
-<li><tt class="docutils literal"><span class="pre">writeDocType()</span></tt> would write something like <tt class="docutils literal"><span class="pre"><!DOCTYPE</span> <span class="pre">HTML</span> <span class="pre">PUBLIC</span>
-<span class="pre">"-//W3C//DTD</span> <span class="pre">HTML</span> <span class="pre">4.01</span> <span class="pre">Transitional//EN"</span>
+<li><tt class="docutils literal"><span class="pre">writeDocType()</span></tt> would write something like
+<tt class="docutils literal"><span class="pre"><!DOCTYPE</span> <span class="pre">HTML</span> <span class="pre">PUBLIC</span> <span class="pre">"-//W3C//DTD</span> <span class="pre">HTML</span> <span class="pre">4.01</span> <span class="pre">Transitional//EN"</span>
<span class="pre">"http://www.w3.org/TR/html4/loose.dtd"></span></tt></li>
-<li>The <head> section of the page is written. <tt class="docutils literal"><span class="pre">title()</span></tt> gives the title, and
+<li>The <head> section of the page is written. <tt class="docutils literal"><span class="pre">title()</span></tt> gives the title, and
you probably want to override it.</li>
-<li><tt class="docutils literal"><span class="pre">writeStyleSheet()</span></tt> is called, if you want to write that or anything else in
-the <head> section.</li>
-<li>The <body> tag is written. Have <tt class="docutils literal"><span class="pre">htBodyArgs()</span></tt> return anything you want in
-the <body> tag (like <tt class="docutils literal"><span class="pre">onLoad="loadImages()"</span></tt>)</li>
+<li><tt class="docutils literal"><span class="pre">writeStyleSheet()</span></tt> is called, if you want to write that or anything else
+in the <head> section.</li>
+<li>The <body> tag is written. Have <tt class="docutils literal"><span class="pre">htBodyArgs()</span></tt> return anything you want in
+the <body> tag (like <tt class="docutils literal"><span class="pre">onLoad="loadImages()"</span></tt>).</li>
<li><tt class="docutils literal"><span class="pre">writeBodyParts()</span></tt> is called, which you may want to override if you want
to create a template for other servlets.</li>
-<li><tt class="docutils literal"><span class="pre">writeContent()</span></tt> should write the main content for the page. This is where
+<li><tt class="docutils literal"><span class="pre">writeContent()</span></tt> should write the main content for the page. This is where
you do most of your display work.</li>
<li>The response is packaged up, the headers put on the front, cookies handled,
-and it's sent to the browser. This is all done for you.</li>
-<li><tt class="docutils literal"><span class="pre">sleep(transaction)</span></tt> is called. This is where you should clean up anything
+and it's sent to the browser. This is all done for you.</li>
+<li><tt class="docutils literal"><span class="pre">sleep(transaction)</span></tt> is called. This is where you should clean up anything
you might have set up earlier -- open files, open database connections, etc.
-Often it's empty. Note that <tt class="docutils literal"><span class="pre">sleep()</span></tt> is called even if an exception was
+Often it's empty. Note that <tt class="docutils literal"><span class="pre">sleep()</span></tt> is called even if an exception was
raised at any point in the servlet processing, so it should (if necessary)
check that each resource was in fact acquired before trying to release it.</li>
-<li>The servlet is placed back into the pool, to be used again. This only happens
+<li>The servlet is placed back into the pool, to be used again. This only happens
after the transaction is complete -- the servlet won't get reused any earlier.</li>
</ul>
-<p>You only have to override the portions that you want to. It is not uncommon to only override the <tt class="docutils literal"><span class="pre">writeContent()</span></tt> method in a servlet, for instance.</p>
-<p>You'll notice a file <tt class="docutils literal"><span class="pre">context/Main.py</span></tt> in your working directory. You can look at it to get a feel for what a servlet might look like. (As an aside, a servlet called <tt class="docutils literal"><span class="pre">Main</span></tt> or <tt class="docutils literal"><span class="pre">index</span></tt> will be used analogous to the <tt class="docutils literal"><span class="pre">index.html</span></tt> file). You can look at it for a place to start experimenting, but here we'll work on developing an entire (small) application, introducing the other concepts as we go along.</p>
+<p>You only have to override the portions that you want to. It is not uncommon to
+only override the <tt class="docutils literal"><span class="pre">writeContent()</span></tt> method in a servlet, for instance.</p>
+<p>You'll notice a file <tt class="docutils literal"><span class="pre">context/Main.py</span></tt> in your working directory. You can look
+at it to get a feel for what a servlet might look like. (As an aside, a servlet
+called <tt class="docutils literal"><span class="pre">Main</span></tt> or <tt class="docutils literal"><span class="pre">index</span></tt> will be used analogous to the <tt class="docutils literal"><span class="pre">index.html</span></tt> file).
+You can look at it for a place to start experimenting, but here we'll work on
+developing an entire (small) application, introducing the other concepts as we
+go along.</p>
</div>
<div class="section" id="a-photo-album">
<h1><a class="toc-backref" href="#id13" name="a-photo-album">A Photo Album</a></h1>
-<p>If you look online, you'll see a huge number of web applications available for an online photo album. The world needs one more!</p>
-<p>You will need the <a class="reference" href="http://www.pythonware.com/products/pil/">Python Imaging Library</a> installed for this example. First we'll use it to find the sizes of the images, and later we will use it to create thumbnails.</p>
-<p>We'll develop the application in iterations -- the iterations are numbered in <tt class="docutils literal"><span class="pre">WebKit/Examples/PhotoAlbum/VersionX</span></tt>.</p>
+<p>If you look online, you'll see a huge number of web applications available for
+an online photo album. The world needs one more!</p>
+<p>You will need the <a class="reference" href="http://www.pythonware.com/products/pil/">Python Imaging Library</a> (PIL) installed for this example.
+First we'll use it to find the sizes of the images, and later we will use it to
+create thumbnails.</p>
+<p>We'll develop the application in two iterations.</p>
<div class="section" id="iteration-1-displaying-files">
<h2><a class="toc-backref" href="#id14" name="iteration-1-displaying-files">Iteration 1: Displaying Files</a></h2>
-<p>For the first iteration, we'll display files that you upload by hand. We do this with two servlets -- one to show the entire album, and another for individual pictures. First, the entire album:</p>
+<p>For simplicity, we will store image files in a subdirectory <tt class="docutils literal"><span class="pre">Pics</span></tt> of the
+default context directory <tt class="docutils literal"><span class="pre">WebwareTest/Context</span></tt> and let the AppServer deliver
+the files. In a production environment, you would place the <tt class="docutils literal"><span class="pre">Pics</span></tt> directory
+outside of the context and let the web server deliver the files directly.</p>
+<p>For the first iteration, we'll display files that you upload by hand to
+the <tt class="docutils literal"><span class="pre">Pics</span></tt> directory.</p>
+<p>We do this with two servlets -- one servlet <tt class="docutils literal"><span class="pre">Main.py</span></tt> to show the entire
+album, and another <tt class="docutils literal"><span class="pre">View.py</span></tt> for individual pictures. Place these two servlets
+in the default context directory. First, <tt class="docutils literal"><span class="pre">Main.py</span></tt>:</p>
<pre class="literal-block">
-from WebKit.Page import Page
+from WebKit.Page import Page # the base class for web pages
import os
-import Image
+import Image # the Python Imaging Library
from urllib import quote as urlEncode
-dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "pics")
+dir = os.path.join(os.path.dirname(__file__), 'Pics')
class Main(Page):
def title(self):
- # It's nice to give a real title, otherwise "Main" would
- # be used.
+ # It's nice to give a real title, otherwise "Main" would be used.
return 'Photo Album'
def writeContent(self):
- # We'll format these simpy, one thumbnail per line.
+ # We'll format these simpy, one thumbnail per line:
for filename in os.listdir(dir):
im = Image.open(os.path.join(dir, filename))
x, y = im.size
# Here we figure out the scaled-down size of the image,
- # so that we preserve the aspect ratio. We'll use fake
+ # so that we preserve the aspect ratio. We'll use fake
# thumbnails, where the image is scaled down by the browser.
- x = int(x * (100.0 / y))
- y = 100
- # note that we are just using % substitution to generate
- # the HTML. There's other ways, but this works well enough.
+ x, y = x * 100 / y, 100
+ # Note that we are just using % substitution to generate
+ # the HTML. There's other ways, but this works well enough.
# We're linking to the View servlet which we'll show later.
- # Notice we use urlEncode -- otherwise we'll encounter bugs
- # if there's a file with an embedded space or other character
- # in it.
- self.write('<p><a href="View?filename=%s">'
- % urlEncode(filename))
- self.write('<img src="../pics/%s" width="%i" height="%i">'
- % (urlEncode(filename), x, y))
- self.write('</a></p>\n')
+ # Notice we use urlEncode -- otherwise we'll encounter bugs if
+ # there's a file with an embedded space or other character in it.
+ url = urlEncode(filename)
+ self.writeln('<p><a href="View?filename=%s">'
+ '<img src="Pics/%s" width="%i" height="%i"></a></p>'
+ % (url, url, x, y))
</pre>
-<p>The servlet <tt class="docutils literal"><span class="pre">View</span></tt> takes one URL parameter of <tt class="docutils literal"><span class="pre">filename</span></tt> -- you can get the value of a URL parameter like <tt class="docutils literal"><span class="pre">self.request().field('filename')</span></tt> -- or, if you want a default value, you can use <tt class="docutils literal"><span class="pre">self.request().field('filename',</span> <span class="pre">defaultValue)</span></tt>. In the likely case you don't want to write <tt class="docutils literal"><span class="pre">self.request()</span></tt> before retrieving each value, do:</p>
+<p>The servlet <tt class="docutils literal"><span class="pre">View</span></tt> takes one URL parameter of <tt class="docutils literal"><span class="pre">filename</span></tt>. You can get
+the value of a URL parameter like <tt class="docutils literal"><span class="pre">self.request().field('filename')</span></tt> or,
+if you want a default value, you can use <tt class="docutils literal"><span class="pre">self.request().field('filename',</span>
+<span class="pre">defaultValue)</span></tt>. In the likely case you don't want to write <tt class="docutils literal"><span class="pre">self.request()</span></tt>
+before retrieving each value, do:</p>
<pre class="literal-block">
req = self.request()
self.write(req.field('username'))
@@ -195,13 +244,13 @@
field = self.request().field
self.write(field('username'))
</pre>
-<p>The individual images are viewed with this servlet:</p>
+<p>So here is our complete <tt class="docutils literal"><span class="pre">View</span></tt> servlet:</p>
<pre class="literal-block">
from WebKit.Page import Page
import os
import Image
from urllib import quote as urlEncode
-dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "pics")
+dir = os.path.join(os.path.dirname(__file__), 'Pics')
class View(Page):
@@ -212,119 +261,110 @@
def writeContent(self):
filename = self.request().field('filename')
im = Image.open(os.path.join(dir, filename))
- self.write('<center>')
- self.write('<img src="../pics/%s" width="%i" height="%i">'
+ self.writeln('<div style="text-align:center">')
+ self.writeln('<h4>%s</h4>' % filename)
+ self.writeln('<img src="Pics/%s" width="%i" height="%i">'
% (self.urlEncode(filename), im.size[0], im.size[1]))
- self.write('<br>\n')
- self.write(filename)
- self.write('<p>\n')
- self.write('<a href="./">Return to Index</a>')
- self.write('</center>')
+ self.writeln('<p><a href="Main">Return to Index</a></p>')
+ self.writeln('</div>')
</pre>
</div>
<div class="section" id="iteration-2-uploading-files">
<h2><a class="toc-backref" href="#id15" name="iteration-2-uploading-files">Iteration 2: Uploading Files</a></h2>
-<p>That was fairly simple -- but usually you want to upload files, potentially through a web interface. Along the way we'll add thumbnail generation using PIL, and slighly improve the image index.</p>
-<p>We'll generate thumbnails kind of on demand, so you can still upload files manually -- thumbnails will be put in <tt class="docutils literal"><span class="pre">pics/thumbs/</span></tt> and have <tt class="docutils literal"><span class="pre">-tn</span></tt> appended just to avoid confusion:</p>
+<p>That was fairly simple -- but usually you want to upload files, potentially
+through a web interface. Along the way we'll add thumbnail generation using
+PIL, and slighly improve the image index.</p>
+<p>We'll generate thumbnails kind of on demand, so you can still upload files
+manually -- thumbnails will be put in the directory <tt class="docutils literal"><span class="pre">Thumbs</span></tt> and have <tt class="docutils literal"><span class="pre">-tn</span></tt>
+appended to the name just to avoid confusion:</p>
<pre class="literal-block">
-from WebKit.Page import Page
+from WebKit.Page import Page # the base page class
import os
-import Image
+import Image # the Python Imaging Library
from urllib import quote as urlEncode
-dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "pics")
+baseDir = os.path.dirname(__file__)
+picsDir = os.path.join(baseDir, 'Pics')
+thumbsDir = os.path.join(baseDir, 'Thumbs')
class Main(Page):
def title(self):
- # It's nice to give a real title, otherwise "Main" would
- # be used.
return 'Photo Album'
def writeContent(self):
+ # The heading:
+ self.writeln('<h1 style="text-align:center">%s</h1>' % self.title())
# We'll format these in a table, two columns wide
- self.write('<table width="100%">\n')
- # col will be 0 or 1, depending if we're on the left or
- # right column.
- col = 0
- filenames = os.listdir(dir)
+ self.writeln('<table width="100%">')
+ col = 0 # will be 0 for the left and 1 for the right column
+ filenames = os.listdir(picsDir)
# We'll sort the files, case-insensitive
filenames.sort(lambda a, b: cmp(a.lower(), b.lower()))
for filename in filenames:
-
- if not col: # right column
- self.write('<tr>')
-
- thumbFilename = os.path.splitext(filename)[0] + "-tn.jp"
- if not os.path.exists(os.path.join(dir, "thumbs",
- thumbFilename)):
- # No thumnail exists -- we have to generate one
- im = Image.open(os.path.join(dir, filename))
+ if not col: # left column
+ self.write('<tr style="text-align:center">')
+ thumbFilename = os.path.splitext(filename)
+ thumbFilename = '%s-tn%s' % thumbFilename
+ if not os.path.exists(os.path.join(thumbsDir, thumbFilename)):
+ # No thumbnail exists -- we have to generate one
+ if not os.path.exists(thumbsDir):
+ # Not even the Thumbs directory exists -- make it
+ os.mkdir(thumbsDir)
+ im = Image.open(os.path.join(picsDir, filename))
im.thumbnail((250, 100))
- # @@ ib: handle GIFs
- im.save(os.path.join(dir, "thumbs", thumbFilename))
+ im.save(os.path.join(thumbsDir, thumbFilename))
else:
- im = Image.open(os.path.join(dir, "thumbs", thumbFilename))
- # note that we are just using % substitution to generate
- # the HTML. There's other ways, but this works well enough.
- # We're linking to the View servlet which we'll show later.
- # Notice we use urlEncode -- otherwise we'll encounter bugs
- # if there's a file with an embedded space or other character
- # in it.
- self.write('<td><a href="View?filename=%s">'
- % urlEncode(filename))
- self.write('<img src="../pics/%s" width="%i" height="%i">'
- % (urlEncode(filename), im.size[0], im.size[1]))
- self.write('<br>Filename: %s<br>Size: %i'
- % (self.htmlEncode(filename),
- os.stat(os.path.join(dir, filename)).st_size))
- self.write('</a></td>\n')
-
- if col:
- self.write('</tr>\n')
+ im = Image.open(os.path.join(thumbsDir, thumbFilename))
+ url = urlEncode(filename)
+ self.writeln('<td><p><a href="View?filename=%s">'
+ '<img src="Pics/%s" width="%i" height="%i"></a></p>'
+ '<p>Filename: %s<br>Size: %i Bytes</p>'
+ % (url, url, im.size[0], im.size[1], filename,
+ os.stat(os.path.join(picsDir, filename)).st_size))
+ if col: # right column
+ self.writeln('</tr>')
col = not col
-
- self.write('</table><p>\n')
- self.write('<center><a href="Upload">Upload an image</a></center>')
+ self.write('</table>')
+ self.write('<p style="text-align:center">'
+ '<a href="Upload">Upload an image</a></p>')
</pre>
-<p>The <tt class="docutils literal"><span class="pre">View</span></tt> servlet we'll leave just like it was. We'll add an <tt class="docutils literal"><span class="pre">Upload</span></tt> servlet. Notice we use <tt class="docutils literal"><span class="pre">enctype="form/multi-part"</span></tt> in the <tt class="docutils literal"><span class="pre"><form></span></tt> tag -- this is an HTMLism for file uploading (otherwise you'll just get the filename and not the file contents). We also add a hidden field <tt class="docutils literal"><span class="pre">doUpload</span></tt> which tells us that the form has been submitted. Finally when the form is finished we redirect them to the viewing page (<tt class="docutils literal"><span class="pre">self.response().sendRedirect(url)</span></tt>):</p>
+<p>The <tt class="docutils literal"><span class="pre">View</span></tt> servlet we'll leave just like it was.</p>
+<p>We'll add an <tt class="docutils literal"><span class="pre">Upload</span></tt> servlet. Notice we use <tt class="docutils literal"><span class="pre">enctype="multipart/form-data"</span></tt>
+in the <tt class="docutils literal"><span class="pre"><form></span></tt> tag -- this is an HTMLism for file uploading (otherwise
+you'll just get the filename and not the file contents). Finally, when the form
+is finished and we have uploaded the image, we redirect them to the viewing
+page by using <tt class="docutils literal"><span class="pre">self.response().sendRedirect(url)</span></tt>:</p>
<pre class="literal-block">
from WebKit.Page import Page
+import os
from urllib import quote as urlEncode
-dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "pics")
+dir = os.path.join(os.path.dirname(__file__), 'Pics')
class Upload(Page):
def writeContent(self):
- if self.request().field('doUpload', 0):
+ if self.request().hasField('imageFile'):
self.doUpload()
return
- self.write('''
- Upload your image:<br>
- <form action="Upload" method="POST" enctype="form/multi-part">
- <input type="hidden" name="doUpload" value="yes">
+ self.writeln('''
+ <h3>Upload your image:</h3>
+ <form action="Upload" method="post" enctype="multipart/form-data">
<input type="file" name="imageFile">
<input type="submit" value="Upload">
- </form>
- ''')
+ </form>''')
def doUpload(self):
file = self.request().field('imageFile')
# Because it's a file upload, we don't get a string back.
# So to get the value we do this:
- contents = file.value
- filename = file.filename
- f = open(os.path.join(dir, filename), 'w')
- f.write(contents)
- f.close()
- self.response().sendRedirect('View?filename=%s'
- % urlEncode(filename))
+ filename, contents = file.filename, file.value
+ open(os.path.join(dir, filename), 'wb').write(contents)
+ url = 'View?filename=' + urlEncode(filename)
+ self.response().sendRedirect(url)
</pre>
</div>
</div>
</div>
-<div class="footer">
-Webware for Python (<a href="http://www.webwareforpython.org">www.webwareforpython.org</a>)
-</div>
</body>
</html>
Modified: Webware/trunk/WebKit/Docs/Tutorial.txt
==============================================================================
--- Webware/trunk/WebKit/Docs/Tutorial.txt (original)
+++ Webware/trunk/WebKit/Docs/Tutorial.txt Wed Sep 28 02:07:11 2005
@@ -192,7 +192,7 @@
outside of the context and let the web server deliver the files directly.
For the first iteration, we'll display files that you upload by hand to
-the ``Pics``directory.
+the ``Pics`` directory.
We do this with two servlets -- one servlet ``Main.py`` to show the entire
album, and another ``View.py`` for individual pictures. Place these two servlets
Modified: Webware/trunk/WebKit/Docs/UsersGuide.html
==============================================================================
--- Webware/trunk/WebKit/Docs/UsersGuide.html (original)
+++ Webware/trunk/WebKit/Docs/UsersGuide.html Wed Sep 28 02:07:11 2005
@@ -9,7 +9,7 @@
</head>
<body>
<div class="document" id="webkit-user-s-guide">
-<h1 class="header">WebKit User's Guide</h1>
+<h1 class="title">WebKit User's Guide</h1>
<p>Webware for Python</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
@@ -373,8 +373,5 @@
Servlets.</p>
</div>
</div>
-<div class="footer">
-Webware for Python (<a href="http://www.webwareforpython.org">www.webwareforpython.org</a>)
-</div>
</body>
</html>
|