A Quick Intro to OpenACS Templating

Why would I want to use OpenACS's templating system?

This is a basic introduction to the templating system in OpenACS.

Why would you want to read this document? Well, if you want to put up a webpage using information from a database, the templating system it what you use to do it.

Background

If you've used HTML to build a webpage before, then you already undertstand a lot of the process. In OpenACS, the webpage that is most similar to the HTML page you're used to is an ADP page.

So, instead of index.html, we'll start with index.adp

What OpenACS adds to HTML is a couple of extentions which allow you to incorporate dynamic information from a database. The dynamic information comes from two other files with the same name as the ADP file, but a different suffix. So for index.adp, you'll also have index.tcl and index.xql (sometimes index-oracle.xql or index-postgresql-xql if the code is database specific. This allows for multiple database support)

OpenACS has a very powerful way of separating code and presentation. If you're working on a large team of programmers, this allows you to let the programmers concentrate on providing datasources for the graphic artists, and let the graphic artists concentrate on making the pages look good.

Overview

The basic idea is you have three files for each webpage: Sometimes it may be confusing to see sql code embedded in the .tcl file. Ignore this, as the SQL code in the .xql file has higher precedence.

These are the three steps you need to take to have things properly abstracted:

Refer to the variables in the .adp file


<p>User 2700 has email:  @email@ and a url: @my_url@</p>

Let's list all the email addresses:
<ol>
<multiple name="foobar">
<li>@foobar.email@</li>
</multiple>
</ol>

Perform the queries in the .tcl file

ad_page_contract {
    Main view page for one project.

    @author jader@bread.com
    @creation-date 2003-05-15
    @cvs-id $Id$

} {
    one_user_id:integer,optional
} -properties {
    email:onevalue
    my_url:onevalue
    foobar:multiple
}

# note how there is no SQL here, just an empty statement {}
# and we use the query_name from the .xql file.

# single row query for num_parties
# sets the value for num_parties in Tcl. The -properties portion of this page
# then exports it to the .adp page
db_1row one_user_select {}

# now we have values for email and my_url

# multirow query for emails
db_multirow foobar emails_select {}
The -properties section that identifies variables that can be used in the .adp file.

Define queries in the .xql file:

<?xml version="1.0"?>
<queryset> 
  <fullquery name="one_user_select"> 
    <querytext> 
        SELECT email, url as my_url 
        FROM parties
        WHERE party_id = '2700'
    </querytext> 
  </fullquery> 

  <fullquery name="emails_select"> 
    <querytext> 
        SELECT email FROM parties
    </querytext> 
  </fullquery> 
</queryset> 

Troubleshooting

A few things to try:

Templating inheritance

to inherit site master, and yet have a local (package or section)
master template, do:

-> in package/section master:
    <master>
    blah
    <slave>

-> in individual adp:
    <master src="path_to_section_master">
    blah
    <slave>

Mapping procedures to sql queries

If you're writing a procedure, then when you refer to the .xql file, the fullquery name has to include the full procedure name, then period, then query name: spm::project::change_order.get_current

Thanks

Dave Hwang's posting http://openacs.org/forums/message-view?message_id=100950
Jim, on IRC
DaveB, on IRC
Alex Vorobiev

Other references

Advanced topics