JOTWeb Users Guide

  1. Overview
  2. Dynamic Pages and Templates Using TAL
  3. Name-spaces
  4. Entity Reference and Cascading
  5. Apache Integration

Overview

JOTWeb uses HTML with TAL tagging for the page markup and templating, and Python modules for the logic to build dynamic web-sites. This creates an effective separation between presentation and logic. Python programmers will feel right at home writing the web-site code, because code is contained in standard python modules. Web-site designers are aided by the use of TAL markup, which is quickly becoming a standard for creation of dynamic web-sites and interoperates well with many HTML and XML editors and other tools.

Currently (July, 2003), JOTWeb is in development. It already has nice modules for form processing and validation and session management. These are heavily oriented towards making the common use of these tasks as easy as possible, while allowing for more complex use. It is planned that this trend will continue as more modules are added.

The goal is to have a system which both HTML and Python coders can feel comfortable with and is simple, elegant and powerful.

Below you will find information using TAL and Python within the JOTWeb framework.

Dynamic Pages and Templates Using TAL

Introduction to TAL

TAL, the Template Attribute Language, uses attributes on existing tags to change their behavior. This allows normal HTML to be extended to produce dynamic output. TAL has been implemented in the Zope framework as "ZPT" or "Zope Page Templates". While ZPT provides a different name-space and some slightly different functionality, the basics of both TAL and ZPT are very similar. The bulk of the ZPT documentation is relavent to TAL.

This document will not go into the specifics of TAL, except to note where the JOTWeb implementation is different other implementations, in particular Zope's ZPT. It is recommended that JOTWeb users review the Zope ZPT/TAL documentation to learn TAL/TALES/METAL.

What are ZPT, TAL, TALES and METAL?

Please see the following ZPT/TAL/TALES/METAL docuemntation for learning to use JOTWeb's templating:

Quickstart

Let's assume that you hvae the following Python code in a file named "code.py":

import random
def iswinner():
   return(random.random() > 0.5)

sitename = 'My Test Site'
subdirlist = [ 'foo', 'bar', 'baz' ]

Dynamic Tag Contents: You can use TAL to dynamically modify your HTML to include the title in your document:

<title tal:content="code/sitename">Title Placeholder</title>

Which would be rendered as:

<title">My Test Site</title>

Tag replacement: You can use tal:replace to replace the full tag, instead of just setting it's content:

Welcome to: <span tal:replace="code/sitename">Name Placeholder</span>

Which would be rendered as:

Welcome to: My Test Site

Conditionals: Parts of your document can be conditionally included by using the tal:condition tag. When the results of the expression is true (using the standard Python idea of "trueness"), the tag is expanded, otherwise it is supressed. For example, the "code/iswinner" function uses the random number generator and there is a 50% chance that it will return true and display "You are a winner!"

<h1>Welcome to my page</h1>
<span tal:condition="code/iswinner">You may already be a winner!</span>

Which would 50% of the time render to the following:

<h1>Welcome to my page</h1>
You may already be a winner!

Variables: Variables can be defined in both the local and global name-spaces. For example:

<span tal:define="global sitename string:My Site"></span>
<span tal:define="pagename string:A Page"></span>
You are on page "<span tal:replace="pagename"></span>" of site "<span
   tal:replace="sitename"></span>".

Which will be rendered as:

You are on page "A Page" of site "My Site".

Iteration: A list or other iteratable type can be looped over using the "tal:repeat" construct. This works like the "tal:define" tag, which creates a variable. The current tag is repeated, with each item of the list. For example, the following creates a "subdir" variable and then displays the name with a line break after it:

<span tal:repeat="subdir code/subdirlist">
   <span tal:replace="subdir">Subdir Placeholder</span><br /></span>

Which will be rendered as:

foo<br />bar<br />baz<br />

Dynamic Attributes: Attributes of existing tags can be set by using "tal:attributes". For example, to create a dynamic list like the above (which combines many of the above):

<span tal:repeat="subdir code/subdirname">
   Go to: <a href="placeholder" tal:attributes="href subdir"
         tal:content="subdir">Link Placeholder</a>
</span>

Which will be rendered as:

Go to: <a href="foo">foo</a>
Go to: <a href="bar">bar</a>
Go to: <a href="baz">baz</a>

Macros: Macros can be used to create templates for how parts of your site looks, with portions filled in later. For example, imagine that you create a file named "standard.html" with the conents:

<div metal:define-macro="header" tal:omit-tag="">
   <head>
      <title><div metal:define-slot="title">Title Placeholder</div></title>
      <link REL="SHORTCUT ICON" HREF="/favicon.ico">
      <link rel="STYLESHEET" href="/style.css" type="text/css">
   </head>
</div>

Then you can create pages which reference this macro and fill in the title element:

<div metal:use-macro="standard/macros/header">
   <div metal:fill-slot="title" tal:omit-tag="">My Home Page</div>
</div>

Which will be rendered as:

   <head>
      <title>My Home Page</title>
      <link REL="SHORTCUT ICON" HREF="/favicon.ico">
      <link rel="STYLESHEET" href="/style.css" type="text/css">
   </head>

Differences from ZPT

The following ZPT constructs do not work under JOTWeb:

Please let me know if other discrepencies are found

Name-spaces

TAL Name-space

TAL tags operate in their own name-space. There are two of these available, local and global. These are very similar in function to local and global variables in python. Local variables exist only in the current scope while global variables (defined with tal:define="global name value") exist for the remaineder of the rendering of the current request.

The TAL name-space can be accessed from Python code using the jotwebutils.getGlobal() and jotwebutils.getLocal() functions.

JOTWeb Root Name-space

JOTWeb includes a name-space in which names related to JOTWeb or the current request are located. In TAL, this is called "jotwebnsroot", and in Python it can be accessed via the "getNSRoot()" method of the "jotwebutils" module.

The following entries are available under "jotwebnsroot":

Configuration Name-space

JOTWeb sets up a number of configuration entries before starting the page rendering. It then looks for a file named "jotweb.conf" in the JOTWeb document root directory and loads entries from that file. Those directives are all loaded before page rendering starts, and is a good place to set up values and objects or even potentially running code, before the page rendering starts.

See the jotweb.config section for more information on the configuration and the default values.

Persistent Name-space

Entries made in this name-space last across requests. Note that multiple requests in succession may hit different instances of the JOTWeb server-side code. For example, Apache may run multiple processes and each one may have it's own JOTWeb server-side instance. Each one of these would have it's own persistent space.

This may be useful for storing information such as database connections, preventing the database connections from having to be set up and torn down with every request.

Note that entries created by JOTWeb's standard library are prefixed with "jotweb_". This prefix should be avoided in your own code. Other libraries may wish to use their own unique prefix to prevent clashes with user code.

Specifying file type: HTML, XHTML, or XML

JOTWeb will compile the template as XML if the file name ends in ".xml". By default, but controlled with the "filetypemagic" config option, JOTWeb will also look at the first line of the file to determine the file type. The file type is set depending on what the first line of the file starts with:

Note that there can be leading space before these strings, but the strings must otherwise appear exactly as above.

See the JOTWeb config documentation for more information on configuration files and the entries available.

Entity Reference and Cascading

Entity Reference

Consider the TAL statement: <span tal:content="name1/name2">

The "name1/name2" references the "name2" entity of "name1". There are three places that TAL looks to find the entity "name1". First, it looks in it's own global name-space. It then looks in the local name-space. Both of these can be set with "tal:define" tags. Finally, it will look in the file-system for a file named "name1.py" or "name1.html".

Note that while in my example I'm using "name1/name2", a two-entity name, these can actually be composed of one or more entities. For example, "name1" and "name1/name2/name3/name4" are both valid entity names.

"name1.html" will mostly be used with METAL for accessing macros that reside in the specified file. Again, you do not list the .html extension when referencing the entity. If there is a file named "name1.py", it is loaded as a Python module and "name2" is looked for as a Python attribute of that module. If "name1" matches a directory, JOTWeb will begin looking for a "name2" entity within that directory (using the rules above).

If an entity resolves to a Python object, sub-entities are resolved (and called, if callable and the "nocall:" TALES path modifier is not set (for example: tal:replace="nocall:code/myfunc"). More on resolving with Python objects is in the following section.

Once a path is resolved, the value of the resulting object or return value of the function call is used in the TAL expression. In the event that an entity cannot be resolved, the path expansion fails. This may be tested for using the "exists:" or "not:" TALES path modifier (for example: tal:condition="exists: code/noexistfunc").

Python Types

In the resolution of a TALES expression, the result may be a python object. If the path in the TALES expression specifies sub-entities of this object, JOTWeb will continue resolving down this chain. For example, suppose you have a file "code.py", which contains:

data = { 'username' : 'jafo', 'homedir' : '/home/jafo' }

The username can be obtained acessed with:

Username: <span tal:replace="code/data/username">Username Placeholder</span>

The following Python types may be accessed as entities in the following ways:

Note that TAL expressions can contain ".." to explicitly reference entities in the file-system directory above this one, as long as that does not take the resolution out of the JOTWeb document root.

Cascading

Cascading is the mechanism JOTWeb uses to make entites available to directories below the current directory. It is similar in spirit to Acquisition or Inheritance or a Search Path, where successive elements are searched trying to resolve an entity. JOTWeb will try to resolve an element in the file-system by first looking in the current directory, then searching directories above it until it reaches the JOTWeb document root.

This can be useful for applying certain standard METAL macros, python objects or modules, and common code to a site, while allowing portions of the site to override certain parts of the standard elements.

For example, you may wish to make a "template.html" which contains a METAL macro that defines the framework that every page has. For example, maybe every page has a standard header and footer, but different body.

This can also be useful for "area menus", menus that change depending on the portion of the site you are in, and even for "site menus", a menu which applies to all pages (and cascades down to all sub-pages). Common code can be defined at the top-level directory, and be accessed by every page in the site (without having to know a relative path to the file), or functions and data can be overridden in certain parts of the site.

For example, maybe you have Canada and Europe directories, which have different implementations of "getdate()" that return differently formatted date strings.

Apache Integration

Overview

Most users will interact with JOTWeb through the Apache web server. JOTWeb includes code to allow it to be called as a content handler from Apache via mod_python. The sample Apache configuration provided with JOTWeb sets up Apache so that files with a ".html" extension are rendered through JOTWeb. This could be changed to ".jot", allowing for static ".html" pages being served up without going through JOTWeb.

httpd.conf Configuration Directives

Below is a list of configuration directives that may be used with JOTWeb. Please see the sample "jotweb-httpd.conf" file provided with JOTWeb for a sample.

mod_python Configuration Directives

The directives below aren't directly JOTWeb provided, but are related to mod_python. Since JOTWeb uses mod_python, these may have an impact on JOTWeb operation. Please see the mod_python documentatoin for more information.

Controlling Headers Via Global Variables

The mod_python connector understands a few different global variables for causing different headers to be sent out based on the value at the end of the page render. You can, of course, use Python code to generate any headers you want. These variables are meant to allow you to easily set expiration headers in the TAL templates.

Here are a list of the available headers. Note that the headers that take a Date argument expect to have a number of seconds from now as the argument. This is because it's fairly hard to generate a relative HTTP Date in TAL.

Index