Creating Pages


Note:  This is an excerpt from the PSP Programmers Reference.  Download and install PSP to review the complete PSP package.

In general, PSP pages are like normal HTML files with two exceptions:

  1. They always have a .PSP file extension
  2. They can have JPython code embedded in them

The ability to embed JPython code within a PSP page is what makes this tool useful as a server-side scripting engine.  Without this ability you would simply have plain HTML files and that wouldn't be any fun at all.  A very simple PSP page is the helloworld.psp page from the samples directory.  Lets take a look at the source code for that page:

$[
### Displays a Hello message to the caller and displays
### their IP address to confirm that PSP is actually working
]$
<HTML>
<HEAD>
<TITLE>Hello World</TITLE>
</HEAD>
<BODY>
$[include banner.psp]$
<H1>Hello World</H1>
<BR>
$[
Response.write( "Hello, %s, from Python Server Pages." % (Request.server["REMOTE_ADDR"]) )
]$
<BR>
If your IP address was in the greeting above, you have installed Python Server Pages correctly.
</BODY>
</HTML>

Hopefully you are already familiar with HTML since this document assumes that you are.  If you ignore the green and blue text, mostly what you see is normal HTML.  As you can guess, the green and blue is the good stuff!

Markers

PSP uses the "$[" and "]$" markers to denote where the embedded JPython code is located.  Anything outside of the markers is sent straight to the user's browser without modification.  Anything within the $[ ]$ markers is executed.  The very first set of markers in the helloworld.psp page are used just to include some comments.  The JPython comment character is a "#" character, however using three comment characters can draw some much needed attention to a comment when it is buried within a large PSP page.

It is very important that the markers match up.  For each open marker $[ you have, there must be a corresponding close marker ]$.  If your pages return errors when you try to run them, suspect unmatched markers first.

Include Statement

The next set of markers within the helloworld.psp example look like this:

$[include banner.psp]$

The include statement shown here is used to bring the contents of an external file into the current PSP page.  In this case the contents of banner.psp are included within helloworld.psp at this exact spot.  This is a handy feature for making your PSP pages modular for easier code reuse or just to split them up into logical units that are eventually combined to make the actual page.

PSP Objects

When PSP executes your page, it provides several objects that your code can use discover information, interact with the browser, and interact with the server.  The helloworld.psp page uses the Response object to write data to the user's browser:

$[
Response.write( "Hello, %s, from Python Server Pages." % (Request.server["REMOTE_ADDR"]) )
]$

The Response.write method will most likely be one of the most frequently called PSP method in your applications.  This method writes the contents of its paramter out to the data stream being sent to the user's browser.   The result of this call is to display a message contaning the user's IP address.   To accomplish this the Request object is also employed.  This object allows your pages to find out the details about the request from the user that started the PSP page running in the first place.  If you want to find out more about the server dictionary a good place to look is the snoop.psp page found in the samples.

Loops, IFs, and other blocks

The snoop.psp page found in samples demonstrates some important concepts in PSP, mainly how to construct blocks of code such as loops or IF statements.

$[
### The Snoop page Loops through the Request.server dictionary and displays
### all of the values.  Request.server contains all the information
### the server knows about the current request (the one that
### fired this page).

Response.buffer = 1
]$
<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual InterDev 1.0">
<META HTTP-EQUIV="Content-Type" content="text/html; charset=iso-8859-1">
<TITLE>PSP Snoop</TITLE>
</HEAD>
<BODY>
$[include banner.psp]$
<H1>PSP Snoop</H1>
<BR>
<PRE>
<H2&gtRequest Headers:</H2>
<table>
$[
for varName in Request.server.keys():
]$
	<tr>
		<td>$[varName]$</td>
		<td>$[Request.server[varName]]$</td>

	</tr>
$[	
end block ]$
</table>
</BODY>
</HTML>

Near the end of snoop.psp, a FOR loop is used to iterate through the Request.server dictionary to find all the keys and print their values.  In this example, a new table row (<tr>) will be output for each value found in Request.server.keys().  With the formatting shown above it should be pretty easy to see that if Request.server.keys contains this list "FOO,BAR,ZOT" that there will be three (3) rows inserted into the table.  Here is a sample of the HTML generated by the snoop.psp page:

<h2>Request Headers:</h2>

<table>
  <tr>
    <td>ACCEPT_CHARSET</td>
    <td>None</td>
  </tr>
  <tr>
    <td>SERVER_PORT</td>
    <td>80</td>
  </tr>
  </font>
</table>

As you can see, each time through the loop, another table row was created.  An IF statement works the same way.  Anything included in the IF's block, whether it is HTML or JPython code, will get executed if the IF statement clause is TRUE.  If the clause is FALSE then the block will not be executed.

Finally, when working with JPython looks in your PSP pages, you have to tell PSP where the code blocks end.  JPython does not require this, but for PSP to generate the HTML correctly it has to be able to match your HTML with the correct block of code.  At the end of your loops make sure you always add an "end block" statement to tell PSP where the block ends.  You will need to use an "end block" statement anytime you use the IF, FOR, or WHILE statements (see the snoop.psp code above for an example of using "end block").

Displaying Variables

Lets rewind and look at a piece of the snoop.psp code again:

<tr>
<td>$[varName]$</td>
<td>$[Request.server[varName]]$</td>

</tr>

In this section of code, right in the middle of some HTML are some short, embedded, JPython statements.  In these cases, PSP treates the embedded code like it was a function and inserts the value into the HTML.  So when varName = "SERVER_PORT" this code is generated:

    <td>SERVER_PORT</td>

Although the second embedded statement is a little harder for PSP to figure out, it is the same to you and me.  PSP evaluates "Request.server[varName]" and then replaces it in the HTML with the value:

    <td>80</td>