Wednesday, September 12, 2007

Zope Page Templates: Getting Started

Introduction

Page Templates are a web page generation tool. They help programmers and designers collaborate in producing dynamic web pages for Zope web applications. Designers can use them to maintain pages without having to abandon their tools, while preserving the work required to embed those pages in an application.

The goal is natural workflow. A designer will use a WYSIWYG HTML editor to create a template, then a programmer will edit it to make it part of an application. As required, the designer can load the template back into his editor and make further changes to its structure and appearance. By taking reasonable steps to preserve the changes made by the programmer, he will not disrupt her application.

Page Templates aim at this goal by adopting three principles:

  1. Play nicely with editing tools.
  2. What you see is very similar to what you get.
  3. Keep code out of templates, except for structural logic.

A Page Template is a model of the pages that it will generate. In particular, it is a valid HTML page. Since HTML is highly structured, and WYSIWYG editors carefully preserve this structure, there are strict limits on the ways in which the programmer can change a page and still respect the first principle.

Who Are They For?

Page Templates are for programmers and designers who need to work together to create dynamic web pages. If you create and edit all of your web pages with a text editor, you might not care for Page Templates. Then again, they can be simpler to use and understand than the alternatve, DTML.

Why Yet Another Template Language?

There are plenty of template systems out there, some of them quite popular, such as ASP, JSP, and PHP. Why invent another?

First, none of these template systems are aimed at HTML designers. Once a page has been converted into a template, it is invalid HTML, making it difficult to work with outside of the application. Each of them violates the first or second principle of Zope Page Templates to one degree or another. Programmers should not "hijack" the work of the designers and turn HTML into software. XMLC, part of the Enhydra project, shares our goal, but requires the programmer to write substantial amounts of Java support code for each template.

Second, all of these systems suffer from failure to separate presentation, logic, and content (data). Their violations of the third principle decrease the scalability of content management and website development efforts that use these systems.

Applying The Principles

Page Templates have a template language (TAL) that consists of special tag attributes. For example, a dynamic page title might look like this:

<pre>
<title content="here/title">Page Title</<title>

</pre> <p> The <code>tal:content</code> attribute is a TAL statement. Since it has an XML namespace (the <code>tal:</code> part) most editing tools will not complain that they don't understand it, and will not remove it. It will not change the structure or appearance of the template when loaded into a WYSIWYG editor or a web browser. The name <code>content</code> indicates that it will set the content of the <code>title</code> tag, and the value "here/title" is an expression providing the text to insert into the tag.

This example also demonstrates the second principle; When you view the template in an editor, the title text will act as a placeholder for the dynamic title text. The template acts like an example of how generated documents should look.

There are template commands for replacing entire tags, their contents, or just some of their attributes. You can repeat a tag several times or omit it entirely. You can join parts of several templates together, and specify simple error handling. All of these capabilities are used to generate document structures. You can't create subroutines or classes, write loops or multi-way tests, or easily express complex algorithms.

The template language is deliberately not as powerful and general-purpose as it could be. It is meant to be used inside of a framework (such as Zope) in which other objects handle business logic and tasks unrelated to page layout.

For instance, template language would be useful for rendering an invoice page, generating one row for each line item, and inserting the description, quantity, price, and so on into the text for each row. It would not be used to create the invoice record in a database or to interact with a credit card processing facility.

Page Template Tutorial: Template Language


Creating a Page Template


If you design pages, you will probably use FTP or WebDAV instead of the Zope Management Interface (ZMI) to create and edit Page Templates. See your Zope adminstrator for instructions. For the very small examples in this introduction, it is much easier to use the ZMI.


If you are a Zope administrator or a programmer, you will probably use the ZMI at least occasionally. You may also use emacs, cadaver, or some other client. See the Zope Administrator's Guide for instructions on setting up Zope to to work with various clients.


Use your web browser to log into the Zope management interface. Choose a Folder (the root is fine) and pick "Page Template" from the drop-down add list. Type "simple_page" in the add form's Id field, then push the "Add and Edit" button.


You should now see the main editing page for the new Page Template. The title is blank, the content-type is text/html , and the default template text is in the editing area.


Now you will create a very simple dynamic page. Type the words "a Simple Page" in the Title field. Edit the template text to look like this:


This is <b tal:replace="template/title">the Title</b>.

Now push the "Save Changes" button. The edit page should show a message confirming that your changes have been saved. If some text starting with <!-- Page Template Diagnostics is added to the template, then check to make sure you typed the example correctly and save it again. You don't need to erase the error comment: once the error is corrected it will go away.


Click on the Test tab. You should see a mostly blank page with "This is a Simple Page." at the top.


Back up, then click on the "Browse HTML source" link under the content-type field. You should see "This is the Title ." Back up again, so that you are ready to edit the example further.


Simple Expressions


The text "template/title" in your simple Page Template is a path expression . This the most commonly used of the expression types defined by the TAL Expression Syntax (TALES). It fetches the title property of the template. Here are some other common path expressions:



  • request/URL: The URL of the current web request.

  • user/getUserName: The authenticated user's login name.

  • container/objectIds: A list of Ids of the objects in the same Folder as the template.


Every path starts with a variable name. If the variable contains the value you want, you stop there. Otherwise, you add a slash ( / ) and the name of a sub-object or property. You may need to work your way through several sub-objects to get to the value you're looking for.


There is a small built in set of variables, such as request and user , that will be listed and described later. You will also learn how to define your own variables.


Inserting Text


In your "simple_page" template, you used the tal:replace statement on a bold tag. When you tested it, it replaced the entire tag with the title of the template. When you browsed the source, you saw the template text in bold. We used a bold tag in order to highlight the difference.


In order to place dynamic text inside of other text, you typically use tal:replace on a span tag. Add the following lines to your example:


<br> The URL is <span tal:replace="request/URL">URL</span>.

The span tag is structural, not visual, so this looks like "The URL is URL." when you view the source in an editor or browser. Remember to take care when editing not to destroy the span or place formatting tags such as b or font inside of it, since they would also be replaced.


If you want to insert text into a tag but leave the tag itself alone, you use tal:content . To set the title of your example page to the template's title property, add the following lines above the other text:


<head> <title tal:content="template/title">The Title</title> </head>

If you open the "Test" tab in a new window, the window's title will be "a Simple Page".


Repeating Structures


Now you will add some context to your page, in the form of a list of the objects that are in the same Folder. You will make a table that has a numbered row for each object, and columns for the id, meta-type, and title. Add these lines to the bottom of your example template:


<table border="1" width="100%"> <tr> <th>#</th><th>Id</th><th>Meta-Type</th><th>Title</th> </tr> <tr tal:repeat="item container/objectValues"> <td tal:content="repeat/item/number">#</td> <td tal:content="item/id">Id</td> <td tal:content="item/meta_type">Meta-Type</td> <td tal:content="item/title">Title</td> </tr> </table>

The tal:repeat statement on the table row means "repeat this row for each item in my container's list of object values". The repeat statement puts the objects from the list into the item variable one at a time, and makes a copy of the row using that variable. The value of "item/id" in each row is the Id of the object for that row.


The name item is not special; You can use any name you like for the variable, as long as it starts with a letter and contains only letters, numbers, and underscores ( _ ). It only exists in the tag that the tal:repeat statement is in, in this case the tr tag; If you tried to use it above or below that tag you would get an error.


Each row in the example is numbered, which requires knowing the number of the current repetition. You might also like to know whether a particular row is the first or last row, or similar information. In each copy of the row, the variable item contains an object from the list. This object doesn't know anything about the repetition, so you can't use item/somename to get this sort of information. This is what the builtin repeat variable is for. By placing the name of the repeating variable after repeat in a path, you can access the repetition count from zero ( index ), from one ( number ), from "A" ( Letter ), and in several other ways. So, the expression repeat/item/number is 1 in the first row, 2 in the second row, and so on.


Since one tal:repeat can be placed inside of another, more than one can be active at the same time. This is why you must write repeat/item/number instead of just repeat/number to get information about the tal:repeat that creates the item variable.


Conditional Elements


View the template, and you'll notice that the table is very dull looking. Let's improve it by shading alternate rows. Copy the second row of the table, then edit it so that it looks like this:


<table border="1" width="100%"> <tr> <th>#</th><th>Id</th><th>Meta-Type</th><th>Title</th> </tr> <tbody tal:repeat="item container/objectValues"> <tr bgcolor="#EEEEEE" tal:condition="repeat/item/even"> <td tal:content="repeat/item/number">#</td> <td tal:content="item/id">Id</td> <td tal:content="item/meta_type">Meta-Type</td> <td tal:content="item/title">Title</td> </tr> <tr tal:condition="repeat/item/odd"> <td tal:content="repeat/item/number">#</td> <td tal:content="item/id">Id</td> <td tal:content="item/meta_type">Meta-Type</td> <td tal:content="item/title">Title</td> </tr> </tbody> </table>

The tal:repeat has not changed, you have just moved it onto the new tbody tag. This is a standard HTML tag meant to group together the body rows of a table, which is how you are using it. There are two rows in the body, with identical columns, and one has a grey background.


View the template's source, and you see both rows. If you had not added the tal:condition statements to the rows, then the template would generate both rows for every item, which is not what you want. The tal:condition statement on the first row ensures that it is only included on even- indexed repetitions, while the second row's condition only lets it appear in odd-indexed repetitions.


A tal:condition statement does nothing if its expression has a true value, but removes the entire statement tag, including its contents, if the value is false. The odd and even properties of repeat/item are either zero or one. The number zero, a blank string, an empty list, and the builtin variable nothing are all false values. Nearly every other value is true, including non-zero numbers, and strings with anything in them (even spaces!).


Defining Variables


Your template will always show at least one row, since the template itself is one of the objects listed. In other circumstances, you might want to account for the possibility that the table will be empty. Suppose you want to simply omit the entire table in this case. You can do this by adding a tal:condition to the table:


<table border="1" width="100%" tal:condition="container/objectValues"

Now, when there are no objects, no part of the table will be included in the output. When there are objects, though, the expression "container/objectValues" will be evaluated twice, which is mildly inefficient. Also, if you wanted to change the expression, you would have to change it in both places.


To avoid these problems, you can define a variable to hold the list, and then use it in both the tal:condition and the tal:repeat . Change the first few lines of the table to look like this:


<table border="1" width="100%" tal:define="items container/objectValues" tal:condition="items"> <tr> <th>#</th><th>Id</th><th>Meta-Type</th><th>Title</th> </tr> <tbody tal:repeat="item items">

The tal:define statement creates the variable items , and you can use it anywhere in the table tag.


Now, suppose that instead of simply leaving the table out when there are no items, you want to show a message. To do this, you place the following above the table:


<h4 tal:condition="not:container/objectValues">There Are No Items</h4>

You can't use your items variable here, because it isn't defined yet. If you move the definition to the h4 tag, you can't use it in the table tag any more, because it becomes a local variable of the h4 tag. You could place the definition on some tag that enclosed both the h4 and the table , but there is a simpler solution. By placing the keyword global in front of the variable name, you can make the definition last from the h4 tag to the bottom of the template:


<h4 tal:define="global items container/objectValues" tal:condition="not:items">There Are No Items</h4> <table border="1" width="100%" tal:condition="items">

The not: in the first tal:condition is an expression type prefix that can be placed in front of any expression. If the expression is true, not: is false, and vice versa.


Changing Attributes


Most, if not all, of the objects listed by your template have an icon property, that contains the path to the icon for that kind of object. In order to show this icon in the meta- type column, you will need to insert this path into the src attribute of an img tag, by editing the meta-type column in both rows to look like this:


<td><img src="/misc_/OFSP/Folder_icon.gif" tal:attributes="src item/icon"> <span tal:replace="item/meta_type">Meta-Type</span> </td>

The tal:attributes statement replaces the src attribute of the image with the value of item/icon . The value of src in the template acts as a placeholder, so that the image is not broken, and is the correct size.


Since the tal:content attribute on the table cell would have replaced the entire contents of the cell, including the image, with the meta-type text, it had to be removed. Instead, you insert the meta-type inline in the same fashion as the URL at the top of the page.


peterbe (Jun 25, 2001 11:21 am; Comment #3) Editor Remark Requested Perhaps also mention how to use ( parameters ) > tal:define="items container/objectValues"

becomes


> tal:define="items python:container.objectValues( Photo )"

or if the objectpath containes . dots:


> tal:define="items container/folder.peter/objectValues"

becomes


> tal:define="itemsobj container/folder.peter/objectValues/; items python:itemsobj( Photo )"

Stop and correct me before I make a fool out of myself.


evan (Jun 25, 2001 1:29 pm; Comment #4) These are good, but belong in part 4, where Python expressions are discussed.

Page Template Tutorial: More TAL


Mixing and Matching Statements


As you have seen in the example template, you can put more than one TAL statement on the same tag. There are three limits you should be aware of, however.



  1. Only one of each kind of statement can be used on a single tag. Since HTML does not allow multiple attributes with the same name, you can't have two tal:define on the same tag.

  2. Both of tal:content and tal:replace cannot be used on the same tag, since their functions conflict.

  3. The order in which you write TAL attributes on a tag does not affect the order in which they execute. No matter how you arrange them, the TAL statements on a tag always execute in the following order: define , condition , repeat , content / replace , attributes .


To get around these limits, you can add another tag and split up the statements between the tags. If there is no obvious tag type that would fit, you can use span or div if it is appropriate for the output to contain an element, or use a tal:block element to have the start and end tags omitted from the document.


For example, if you want to define a variable for each repetition of a paragraph, you can't place the tal:define on the same tag as the tal:repeat , since the definition would happen before all of the repetitions. Instead, you would write either of the following:


<div tal:repeat="p phrases"> <p tal:define="n repeat/p/number"> Phrase number <span tal:replace="n">1</span> is "<span tal:replace="p">Phrase</span>".</p> </div> <p tal:repeat="p phrases"> <span tal:define="n repeat/p/number"> Phrase number <span tal:replace="n">1</span> is "<span tal:replace="p">Phrase</span>".</span> </p>

Statements with Multiple Parts


If you need to set multiple attributes on a tag, you can't do it by placing multiple tal:attributes statements on the tag, and splitting them across tags is useless.


Both the tal:attributes and tal:define statements can have multiple parts in a single statement. You separate the parts with semicolons ( ; ), so any semicolon appearing in an expression in one of these statements must be escaped by doubling it ( ;; ). Here is an example of setting both the src and alt attributes of an image:


<img src="default.jpg" tal:attributes="src item/icon; alt item/id">

Here is a mixture of variable definitions:


<span tal:define="global logo here/logo.gif; ids here/objectIds">

String Expressions


String expressions allow you to easily mix path expressions with text. All of the text after the leading string: is taken and searched for path expressions. Each path expression must be preceded by a dollar sign ( $ ). If it has more than one part, or needs to be separated from the text that follows it, it must be surrounded by braces ( {} ). Since the text is inside of an attribute value, you can only include a double quote by using the entity syntax """. Since dollar signs are used to signal path expressions, a literal dollar sign must be written as two dollar signs ( $$ ). For example:


"string:Just text." "string:&copy; $year, by Me." "string:Three ${vegetable}s, please." "string:Your name is ${user/getUserName}!"

Nocall Path Expressions


An ordinary path expression tries to render the object that it fetches. This means that if the object is a function, Script, Method, or some other kind of executable thing, then expression will evaluate to the result of calling the object. This is usually what you want, but not always. For example, if you want to put a DTML Document into a variable so that you can refer to its properties, you can't use a normal path expression because it will render the Document into a string.


If you put the nocall: expression type prefix in front of a path, it prevents the rendering and simply gives you the object. For example:


<span tal:define="doc nocall:here/aDoc" tal:content="string:${doc/id}: ${doc/title}"> Id: Title</span>

This expression type is also valuable when you want to define a variable to hold a function or class from a module, for use in a Python expression.


Python Expressions


A Python expression starts with python: , followed by an expression written in the Python language. See the section on writing Python expressions for more information.


Other Builtin Variables


You have already seen some examples of the builtin variables template , user , repeat , and request . Here is a complete list of the other builtin variables and their uses:



  • nothing : a false value, similar to a blank string, that you can use in tal:replace or tal:content to erase a tag or its contents. If you set an attribute to nothing , the attribute is removed from the tag (or not inserted), unlike a blank string.

  • default : a special value that doesn't change anything when used in tal:replace , tal:content , or tal:attributes . It leaves the template text in place.

  • options : the keyword arguments, if any, that were passed to the template.

  • attrs : a dictionary of attributes of the current tag in the template. The keys are the attributes names, and the values are the original values of the attributes in the template.

  • root : the root Zope object. Use this to get Zope objects from fixed locations, no matter where your template is placed or called.

  • here : the object on which the template is being called. This is often the same as the container , but can be different if you are using acquisition. Use this to get Zope objects that you expect to find in different places depending on how the template is called.

  • container : the container (usually a Folder) in which the template is kept. Use this to get Zope objects from locations relative to the template's permanent home.

  • modules : the collection of Python modules available to templates. See the section on writing Python expressions.


Alternate Paths


The path template/title is guaranteed to exist every time the template is used, although it may be a blank string. Some paths, such as request/form/x , may not exist during some renderings of the template. This normally causes an error when the path is evaluated.


When a path doesn't exist, you often have a fallback path or value that you would like to use instead. For instance, if request/form/x doesn't exist, you might want to use here/x instead. You can do this by listing the paths in order of preference, separated by vertical bar characters ( | ):


<h4 tal:content="request/form/x | here/x">Header</h4>

Two variables that are very useful as the last path in a list of alternates are nothing and default . Use nothing to blank the target if none of the paths is found, or default to leave the example text in place.


You can also test the existence of a path directly with the exists: expression type prefix. A path expression with exists: in front of it is true if the path exists, false otherwise. These examples both display an error message only if it is passed in the request:


<h4 tal:define="err request/form/errmsg | nothing" tal:condition="err" tal:content="err">Error!</h4> <h4 tal:condition="exists:request/form/errmsg" tal:content="request/form/errmsg">Error!</h4>

Dummy Elements


You can include page elements that are visible in the template but not in generated text by using the builtin variable nothing , like this:


<tr tal:replace="nothing"> <td>10213</td><td>Example Item</td><td>$15.34</td> </tr>

This can be useful for filling out parts of the page that will take up more of the generated page than of the template. For instance, a table that usually has ten rows will only have one row in the template. By adding nine dummy rows, the template's layout will look more like the final result.


Inserting Structure


Normally, the tal:replace and tal:content statements quote the text that they insert, converting '< to <', for instance. If you actually want to insert the unquoted text, you need to precede the expression with the structure keyword. Given a variable copyright , the following two lines:


<span tal:replace="copyright">Copyright 2000</span> <span tal:replace="structure copyright">Copyright 2000</span>

might generate "&copy; 2001 By <b>Me</b>" and "© 2001 By Me " respectively.


This feature is especially useful when you are inserting a fragment of HTML that is stored in a property or generated by another Zope object. For instance, you may have news items that contain simple HTML markup such as bold and italic text when they are rendered, and you want to preserve this when inserting them into a "Top News" page. In this case, you might write:


<p tal:repeat="article topnewsitems" tal:content="structure article">A News Article</p> jwm (Aug 8, 2001 7:12 pm; Comment #2) Editor Remark Requested Multiple Defines: > <span tal:define="global logo here/logo.gif; ids here/objectIds">

global is a keyword used per variable definition, so in this case logo becomes global, will ids stays local to the span. A bit like you'd expect, really :-)


Strings:


How about some examples of them in action straight after the construction examples. I find when I hit something I don't quite understand I tend to stall, and in this case I didn't see where I'd use a string construct until I read the fairly unrelated example for nocall below it.


So we'd have something like this:


> "string:Just text." > "string:� $year, by Me." > "string:Three ${vegetable}s, please." > "string:Your name is ${user/getUserName}!"

Which are used like this:


Boring text


You are logged in as someone.


Actually on further reading, I think just mentioning that we're talking about expresion type prefixes that are things that appear inside the attribute strings created when you use a statement (ie, any of tal:define, etc) just before statements would clear this up.


LRA (Jan 10, 2002 7:14 pm; Comment #3) Navigation:

benster (Jun 29, 2002 11:00 pm; Comment #4) Editor Remark Requested Under Mixing and Matching Statements: > For example, if you want to define a variable for each > repetition of a paragraph ...

Where is the paragraph defined? Is it a string variable? It's not a string expression, judging from the examples. It would be helpful to see this paragraph being defined.


FredDrake ? The paragraph is the p element shown in the example. There's nothing magical about this.

Page Template Tutorial: Advanced Concepts





Basic Python Expressions


The Python language is a simple and expressive one. If you have never encountered it before, you should read one of the excellent tutorials or introductions available at the website http://www.python.org.


A Page Template Python expression can contain anything that the Python language considers an expression. You can't use statements such as if and while , and Zope's security restrictions are applied.


Comparisons


One place where Python expressions are practically necessary is in tal:condition statements. You usually want to compare two strings or numbers, and there isn't any other way to do that. You can use the comparison operators < (less than), > (greater than), '== (equal to), and !=' (not equal to). You can also use the boolean operators and , not , and or . For example:


<p tal:repeat="widget widgets"> <span tal:condition="python:widget.type == 'gear'> Gear #<span tal:replace="repeat/widget/number>1</span>: <span tal:replace="widget/name">Name</span> </span> </p>

Sometimes you want to use choose different values inside a single statement based on one or more conditions. You can do this with the test() function, like this:


You <span tal:define="name user/getUserName" tal:replace="python:test(name=='Anonymous User', 'need to log in', default)"> are logged in as <span tal:replace="name">Name</span> </span> <tr tal:define="oddrow repeat/item/odd" tal:attributes="class python:test(oddrow, 'oddclass', 'evenclass')">

Using other Expression Types


You can use other expression types inside of a Python expression. Each type has a corresponding function with the same name, including path() , string() , exists() , and nocall() . This allows you to write expressions such as:


"python:path('here/%s/thing' % foldername)" "python:path(string('here/$foldername/thing'))" "python:path('request/form/x') or default"

The final example has a slightly different meaning than the path expression "request/form/x | default", since it will use the default text if "request/form/x" doesn't exists or if it is false.


Getting at Zope Objects


Much of the power of Zope involves tying together specialized objects. Your Page Templates can use Scripts, SQL Methods, Catalogs, and custom content objects. In order to use them, you have to know how to get access to them.


Object properties are usually attributes, so you can get a template's title with the expression "template.title". Most Zope objects support acquisition, which allows you to get attributes from "parent" objects. This means that the Python expression "here.Control_Panel" will acquire the Control Panel object from the root Folder. Object methods are attributes, as in "here.objectIds" and "request.set". Objects contained in a Folder can be accessed as attributes of the Folder, but since they often have Ids that are not valid Python identifiers, you can't use the normal notation. For example, instead of writing "here.penguin.gif", you must write "getattr(here, penguin.gif )".


Some objects, such as request , modules , and Zope Folders support item access. Some examples of this are:


request['URL'], modules['math'], and here['thing']

When you use item access on a Folder, it doesn't try to acquire the name, so it will only succeed if there is actually an object with that Id contained in the Folder.


As shown in previous chapters, path expressions allow you to ignore details of how you get from one object to the next. Zope tries attribute access, then item access. You can write "here/images/penguin.gif" instead of "python:getattr(here.images, penguin.gif )", and "request/form/x" instead of "python:request.form['x']".


The tradeoff is that path expressions don't allow you to specify those details. For instance, if you have a form variable named "get", you must write "python:request.form['get']", since "request/form/get" will evaluate to the "get" method of the form dictionary.


Using Scripts


Script objects are often used to encapsulate business logic and complex data manipulation. Any time that you find yourself writing lots of TAL statements with complicated expressions in them, you should consider whether you could do the work better in a Script.


Each Script has a list of parameters that it expects to be given when it is called. If this list is empty, then you can use the Script by writing a path expression. Otherwise, you will need to use a Python expression, like this:


"python:here.myscript(1, 2)" "python:here.myscript('arg', foo=request.form['x'])"

If you want to return more than a single bit of data from a Script to a Page Template, it is a good idea to return it in a dictionary. That way, you can define a variable to hold all the data, and use path expressions to refer to each bit. For example:


getPerson returns this: {'name': 'Fred', 'age': 25} <span tal:define="person here/getPerson" tal:replace="string:${person/name} is ${person/age}"> Name is 30</span> years old.

Calling DTML


Unlike Scripts, DTML Methods don't have an explicit parameter list. Instead, they expect to be passed a client, a mapping, and keyword arguments. They use these to construct a namespace.


When the ZPublisher ? publishes a DTML object, it passes the context of the object as the client, and the REQUEST as the mapping. When one DTML object calls another, it passes its own namespace as the mapping, and no client.


If you use a path expression to render a DTML object, it will pass a namespace with request , here , and the template's variables already on it. This means that the DTML object will be able to use the same names as if it were being published in the same context as the template, plus the variable names defined in the template.


Python Modules


The Python language comes with a large number of modules, which provide a wide variety of capabilities to Python programs. Each module is a collection of Python functions, data, and classes related to a single purpose, such as mathematical calculations or regular expressions.


Several modules, including "math" and "string", are available in Python Expressions by default. For example, you can get the value of π from the math module by writing "python:math.pi". To access it from a path expression, however, you need to use the modules variable. In this case, you would use "modules/math/pi". Please refer to the Zope Book or a DTML reference guide for more information about these modules.


The string module is hidden in Python expressions by the "string" expression type function, so you need to access it through the modules variable. You can do this directly in an expression in which you use it, or define a global variable for it, like this:


tal:define="global mstring modules/string" tal:replace="python:mstring.join(slist, ':')"

As long as you're using Python 2.0 or newer, you can avoid this in many cases using string methods:


tal:replace="python:':'.join(slist)"

Modules can be grouped into packages, which are simply a way of organizing and naming related modules. For instance, Zope's Python-based Scripts are provided by a collection of modules in the " PythonScripts " subpackage of the Zope "Products" package. In particular, the "standard" module in this package provides a number of useful formatting functions that are standard in the DTML "Var" tag. The full name of this module is "Products. PythonScripts .standard", so you could get access to it using either of the following statements:


tal:define="pps modules/Products.PythonScripts.standard" tal:define="pps python:modules['Products.PythonScripts.standard']"

Most Python modules cannot be accessed from Page Templates, DTML, or Scripts unless you add Zope security assertions to them. That's outside the scope of this document, and is covered by the Zope Security Guide.

No comments:

About Me

Ordinary People that spend much time in the box
Powered By Blogger