"Your examples just crystalized in my brain and caused me to grasp
some concepts about ZPT that have been driving me nutz!"
- Matthew Stott
"Anyway, thanks again for a great page.
It helped me get started with ZPT and now
I'm hooked!"
- Paul Winkler
So I've been experimenting a bit with ZPT (Zope Page Templates).
It uses something called TAL instead of DTML code to do some business logic in the templates.
To learn this I thought it would be useful to understand/learn TAL using by knowledge in DTML.
I also hope very much that this will help others like me.
Email [email protected] about changes/additions please.
Or visit my website on www.peterbe.com
DTML
<dtml-with "subfolder.index_html">
<a href="<dtml-var absolute_url>" title="<dtml-var title>"><dtml-var title></a>
</dtml-with>
ZPT
<a href="dummylink.html" title="Dynamic Title"
tal:define="doc nocall:context/subfolder/index_html;title doc/title"
tal:attributes="href doc/absolute_url; title title"
tal:content="title">Dynamic Title</a>
DTML
<H1><dtml-var "subfolder[strid].title"></H1>
ZPT
<H1 tal:content="python:path('context/subfolder/%s/title' % strid)">
Varying Title</H1>
DTML
<dtml-var "'?a=b'" url_quote>
ZPT
<span tal:define="pss modules/Products/PythonScripts/standard"
tal:replace="python:pss.url_quote('?a=b')"></span>
(nb. extract from Products.PythonScripts.standard:
from DocumentTemplate.DT_Var import special_formats, \
whole_dollars, dollars_and_cents, structured_text, sql_quote, \
html_quote, url_quote, url_quote_plus, newline_to_br, thousands_commas
DTML
context.manage_addDTMLMethod('id',title='Title',file='<dtml-var username>')
ZPT
context.manage_addZopePageTemplate('id')
context['id'].pt_setTitle('Title')
context['id'].write('<div tal:replace="context/username" />')
DTML
<textarea name="users:list"
><dtml-in "getUsers()"><dtml-var sequence-item><dtml-unless sequence-end>
</dtml-unless></dtml-in></textarea>
ZPT
<textarea name="users:list"
tal:define="users context/getUsers | nothing; string modules/string"
tal:content="python:string.join(users or [],'\n')"></textarea>
DTML
<dtml-unless "REQUEST.has_key('usernames')">
<dtml-call "REQUEST.set('usernames',[])">
</dtml-unless>
<select name="usernames:list">
<dtml-in usernames>
<option <dtml-if "_['sequence-item'] in REQUEST['usernames']">selected</dtml-if>
><dtml-var sequence-item></option>
</dtml-in>
</select>
ZPT
<select name="usernames:list" tal:define="emptylist python:[];
usernames python:context.getUsernames();
selectedones request/usernames | emptylist">
<option tal:repeat="username usernames"
tal:attributes="selected python:username in selectedones"
tal:content="python:username">displayname</option>
</select>
DTML
<dtml-var image1>
ZPT
<div tal:replace="structure container/image1">image goes here</div>
<img tal:replace="structure container/image1" alt="image goes here" src="dummy.jpg" />
DTML
<dtml-let i2="_['image2.jpg'].absolute_url()">
<a href="&dtml-i2;">Image2.jpg</a>
</dtml-let>
ZPT
<a href=""
tal:attributes="href container/image2.jpg/absolute_url">
Image2.jpg
</a>
cheers Paul Winkler for this one!
DTML
<ul>
<dtml-in "objectValues(['Link', 'Favorite'])" skip_unauthorized>
<li><dtml-var sequence-item></li>
</dtml-in>
</ul>
ZPT
<ul tal:define="ztu modules/ZTUtils;
objs python:context.objectValues(['Link', 'Favorite']);
authobjs python:ztu.LazyFilter(objs, skip='')">
<li tal:repeat="obj authobjs"></li>
DTML
<dtml-var something html_quote>
ZPT
<span tal:replace="template/something | container/something | options/something |
root/something | request/something"/>
DTML
:: in object standard_html_header ::
<dtml-if "determineStyle()=='simple'">
<dtml-var standard_html_header_simple>
<dtml-else>
<dtml-var standard_html_header_default>
</dtml-if>
ZPT
:: in object index_html ::
<html metal:use-macro="context/getStyle">
:: in object getStyle (Python Script) ::
if context.determineStyle()=='simple':
return context.standard_master_simple.macros['standard']
else:
return context.standard_master_default.macros['standard']
----
Note that the Page Template objects 'standard_master_simple'
and 'standard_master_default' both start
like this:
<html metal:define-macro="standard">
DTML
<H4>
<dtml-if "_.len(result)==0">
<dtml-var document_title>
<dtml-else>
Untitled
</dtml-if>
</H4>
ZPT
<H4>
<span tal:replace="template/title"
tal:condition="python:len(result)==0"/>
<span tal:replace="string:Untitled"
tal:condition="python:not(len(result)==0)"/>
</H4>
or
<h4 tal:content="python:test(len(result)==0, default,
path('template/title'))">Untitled</h4>
DTML
<dtml-in somesequence>
<li><dtml-var sequence-item>
<dtml-unless sequence-end>
<br>
</dtml-unless>
</dtml-in>
ZPT
<span tal:repeat="item context/somesequence">
<li tal:content="item"></li>
<br tal:condition="not:repeat/item/end"/>
</span>
---
See further RepeatVariable
DTML
<p>
<dtml-try>
My name is <dtml-var SlimShady>
<dtml-except>
Noops. No slim
</dtml-try>
</p>
ZPT
<p tal:on-error="string: Noops. No slim">
My name is <span tal:replace="context/SlimShady" />.
</p>
DTML
<dtml-if "REQUEST.has_key('b_start')">
<dtml-call "REQUEST.set('b_start',_.int(b_start))">
<dtml-else>
<dtml-call "REQUEST.set('b_start',0)">
</dtml-if>
<dtml-call "REQUEST.set('size', 3)">
<dtml-call "REQUEST.set('foods',['sandwiches', 'pie', 'meatloaf',
'berries', 'bread', 'coffee',
'some', 'thing', 'else'])">
<a href="?b_start=<dtml-var "b_start-size">">Previous <dtml-var size></a>
<dtml-in foods size=size orphan=1 start=b_start>
<p>
<dtml-var sequence-item>
</p>
</dtml-in>
<a href="?b_start=<dtml-var "b_start+size">">Next <dtml-var size></a>
ZPT
<div tal:define="b_start python:path('request/b_start') or 0;
results python:context.listProducts(popular=0);
Batch python:modules['ZTUtils'].Batch;
global batch python:Batch(results, 5, int(b_start),
orphan=1)"
tal:replace="nothing" />
<a href="nextbatch" tal:define="p batch/previous"
tal:condition="p"
tal:attributes="href string:?b_start=${p/first}">
Previous <span tal:replace="p/length">n</span>
</a>
<p tal:repeat="food batch">
<span tal:replace="food">food</span>,
</p>
<a href="nextbatch" tal:define="n batch/next"
tal:condition="n"
tal:attributes="href string:?b_start=${batch/end}">
Next <span tal:replace="n/length">n</span>
</a>
DTML
<a href="mailto:<dtml-var webmaster>?subject=<dtml-var document_title>">
Email webmaster</a>
ZPT
<a tal:attributes="href string:mailto:${context/webmaster}?subject=${template/title}"
href=""
>Email webmaster</a>
DTML
<dtml-var knife missing>
<dtml-var fork missing="Bring one next time will ya">
<dtml-var spoon null="At least it's an empty spoon">
ZPT
<span tal:replace="knife | nothing" />
<span tal:replace="fork | default">Bring one next time will ya</span>
<span tal:replace="python:spoon or default">At least it's an empty
spoon</span>
DTML
<ul>
<dtml-in "mydb.selectbyname(name='peter')">
<li><dtml-var surname>
</dtml-in>
</ul>
ZPT
<ul tal:define="sequence python:container.mydb.selectbyname(name='peter')">
<li tal:repeat="item sequence">
<span tal:replace="item/surname">surname</span></li>
</ul>
DTML
<dtml-var REQUEST>
ZPT
<span tal:replace="structure request">info about the request namespace</span>
DTML
<p>
<dtml-var document_title>
<dtml-var title>
</p>
ZPT
<p>
<span tal:replace="python:path('template/title')">python:path('template/title')</span>
<span tal:replace="python:path('context/title')">python:path('context/title')</span>
</p>
[or]
<p>
<span tal:replace="python:template.title">python:template.title</span>
<span tal:replace="python:context.title">python:context.title</span>
</p>