summaryrefslogtreecommitdiff
path: root/www/users_guide/inheritanceEtc.rst
diff options
context:
space:
mode:
Diffstat (limited to 'www/users_guide/inheritanceEtc.rst')
-rw-r--r--www/users_guide/inheritanceEtc.rst517
1 files changed, 517 insertions, 0 deletions
diff --git a/www/users_guide/inheritanceEtc.rst b/www/users_guide/inheritanceEtc.rst
new file mode 100644
index 0000000..1b8136d
--- /dev/null
+++ b/www/users_guide/inheritanceEtc.rst
@@ -0,0 +1,517 @@
+Import, Inheritance, Declaration and Assignment
+===============================================
+
+(inheritanceEtc)
+
+#import and #from directives
+----------------------------
+
+(inheritanceEtc.import)
+
+Syntax:
+
+::
+
+ #import MODULE_OR_OBJECT [as NAME] [, ...]
+ #from MODULE import MODULE_OR_OBJECT [as NAME] [, ...]
+
+The {#import} and {#from} directives are used to make external
+Python modules or objects available to placeholders. The syntax is
+identical to the import syntax in Python. Imported modules are
+visible globally to all methods in the generated Python class.
+
+::
+
+ #import math
+ #import math as mathModule
+ #from math import sin, cos
+ #from math import sin as _sin
+ #import random, re
+ #from mx import DateTime # ## Part of Egenix's mx package.
+
+After the above imports, {$math}, {$mathModule}, {$sin}, {$cos} and
+{$\_sin}, {$random}, {$re} and {$DateTime} may be used in
+{$placeholders} and expressions.
+
+#extends
+--------
+
+(inheritanceEtc.extends)
+
+Syntax:
+
+::
+
+ #extends CLASS
+
+All templates are subclasses of {Cheetah.Template.Template}.
+However, it's possible for a template to subclass another template
+or a pure Python class. This is where {#extends} steps in: it
+specifies the parent class. It's equivalent to PSP's
+{"@page extends="} directive.
+
+Cheetah imports the class mentioned in an {#extends} directive
+automatically if you haven't imported it yet. The implicit
+importing works like this:
+
+::
+
+ #extends Superclass
+ ## Implicitly does '#from Superclass import Superclass'.
+
+ #extends Cheetah.Templates.SkeletonPage
+ ## Implicitly does '#from Cheetah.Templates.SkeletonPage import SkeletonPage'.
+
+If your superclass is in an unusual location or in a module named
+differently than the class, you must import it explicitly. There is
+no support for extending from a class that is not imported; e.g.,
+from a template dynamically created from a string. Since the most
+practical way to get a parent template into a module is to
+precompile it, all parent templates essentially have to be
+precompiled.
+
+There can be only one {#extends} directive in a template and it may
+list only one class. In other words, templates don't do multiple
+inheritance. This is intentional: it's too hard to initialize
+multiple base classes correctly from inside a template. However,
+you can do multiple inheritance in your pure Python classes.
+
+If your pure Python class overrides any of the standard {Template}
+methods such as {.\_\_init\_\_} or {.awake}, be sure to call the
+superclass method in your method or things will break. Examples of
+calling the superclass method are in section
+tips.callingSuperclassMethods. A list of all superclass methods is
+in section tips.allMethods.
+
+In all cases, the root superclass must be {Template}. If your
+bottommost class is a template, simply omit the {#extends} in it
+and it will automatically inherit from {Template}. { If your
+bottommost class is a pure Python class, it must inherit from
+{Template} explicitly: }
+
+::
+
+ from Cheetah.Template import Template
+ class MyPurePythonClass(Template):
+
+If you're not keen about having your Python classes inherit from
+{Template}, create a tiny glue class that inherits both from your
+class and from {Template}.
+
+Before giving any examples we'll stress that Cheetah does { not}
+dictate how you should structure your inheritance tree. As long as
+you follow the rules above, many structures are possible.
+
+Here's an example for a large web site that has not only a general
+site template, but also a template for this section of the site,
+and then a specific template-servlet for each URL. (This is the
+"inheritance approach" discussed in the Webware chapter.) Each
+template inherits from a pure Python class that contains
+methods/attributes used by the template. We'll begin with the
+bottommost superclass and end with the specific template-servlet:
+
+::
+
+ 1. SiteLogic.py (pure Python class containing methods for the site)
+ from Cheetah.Template import Template
+ class SiteLogic(Template):
+
+ 2. Site.tmpl/py (template containing the general site framework;
+ this is the template that controls the output,
+ the one that contains "<HTML><HEAD>...", the one
+ that contains text outside any #def/#block.)
+ #from SiteLogic import SiteLogic
+ #extends SiteLogic
+ #implements respond
+
+ 3. SectionLogic.py (pure Python class with helper code for the section)
+ from Site import Site
+ class SectionLogic(Site)
+
+ 4. Section.tmpl/py (template with '#def' overrides etc. for the section)
+ #from SectionLogic import SectionLogic
+ #extends SectionLogic
+
+ 5. page1Logic.py (pure Python class with helper code for the template-servlet)
+ from Section import Section
+ class indexLogic(Section):
+
+ 6. page1.tmpl/py (template-servlet for a certain page on the site)
+ #from page1Logic import page1Logic
+ #extends page1Logic
+
+A pure Python classes might also contain methods/attributes that
+aren't used by their immediate child template, but are available
+for any descendant template to use if it wishes. For instance, the
+site template might have attributes for the name and e-mail address
+of the site administrator, ready to use as $placeholders in any
+template that wants it.
+
+{ Whenever you use {#extends}, you often need {#implements} too,}
+as in step 2 above. Read the next section to understand what
+{#implements} is and when to use it.
+
+#implements
+-----------
+
+(inheritanceEtc.implements)
+
+Syntax:
+
+::
+
+ #implements METHOD
+
+You can call any {#def} or {#block} method directly and get its
+outpt. The top-level content - all the text/placeholders/directives
+outside any {#def}/{#block} - gets concatenated and wrapped in a
+"main method", by default {.respond()}. So if you call
+{.respond()}, you get the "whole template output". When Webware
+calls {.respond()}, that's what it's doing. And when you do 'print
+t' or 'str(t)' on a template instance, you're taking advantage of
+the fact that Cheetah makes {.\_\_str\_\_()} an alias for the main
+method.
+
+That's all fine and dandy, but what if your application prefers to
+call another method name rather than {.respond()}? What if it wants
+to call, say, {.send\_output()} instead? That's where {#implements}
+steps in. It lets you choose the name for the main method. Just put
+this in your template definition:
+
+::
+
+ #implements send_output
+
+When one template extends another, every template in the
+inheritance chain has its own main method. To fill the template,
+you invoke exactly one of these methods and the others are ignored.
+The method you call may be in any of the templates in the
+inheritance chain: the base template, the leaf template, or any in
+between, depending on how you structure your application. So you
+have two problems: (1) calling the right method name, and (2)
+preventing an undesired same-name subclass method from overriding
+the one you want to call.
+
+Cheetah assumes the method you will call is {.respond()} because
+that's what Webware calls. It further assumes the desired main
+method is the one in the lowest-level base template, because that
+works well with {#block} as described in the Inheritance Approach
+for building Webware servlets (section webware.inheritance), which
+was originally the principal use for Cheetah. So when you use
+{#extends}, Cheetah changes that template's main method to
+{.writeBody()} to get it out of the way and prevent it from
+overriding the base template's {.respond()}.
+
+Unfortunately this assumption breaks down if the template is used
+in other ways. For instance, you may want to use the main method in
+the highest-level leaf template, and treat the base template(s) as
+merely a library of methods/attributes. In that case, the leaf
+template needs {#implements respond} to change its main method name
+back to {.respond()} (or whatever your application desires to
+call). Likewise, if your main method is in one of the intermediate
+templates in an inheritance chain, that template needs {#implements
+respond}.
+
+The other way the assumption breaks down is if the main method {
+is} in the base template but that template extends a pure Python
+class. Cheetah sees the {#extends} and dutifully but incorrectly
+renames the method to {.writeBody()}, so you have to use
+{#implements respond} to change it back. Otherwise the dummy
+{.respond()} in {Cheetah.Template} is found, which outputs...
+nothing. { So if you're using {#extends} and get no output, the {
+first} thing you should think is,
+"Do I need to add {#implements respond} somewhere?" }
+
+#set
+----
+
+(inheritanceEtc.set)
+
+Syntax:
+
+::
+
+ #set [global] $var = EXPR
+
+{#set} is used to create and update local variables at run time.
+The expression may be any Python expression. Remember to preface
+variable names with $ unless they're part of an intermediate result
+in a list comprehension.
+
+Here are some examples:
+
+::
+
+ #set $size = $length * 1096
+ #set $buffer = $size + 1096
+ #set $area = $length * $width
+ #set $namesList = ['Moe','Larry','Curly']
+ #set $prettyCountry = $country.replace(' ', '&nbsp;')
+
+{#set} variables are useful to assign a short name to a
+{$deeply.nested.value}, to a calculation, or to a printable version
+of a value. The last example above converts any spaces in the
+'country' value into HTML non-breakable-space entities, to ensure
+the entire value appears on one line in the browser.
+
+{#set} variables are also useful in {#if} expressions, but remember
+that complex logical routines should be coded in Python, not in
+Cheetah!
+
+::
+
+ #if $size > 1500
+ #set $adj = 'large'
+ #else
+ #set $adj = 'small'
+ #end if
+
+Or Python's one-line equivalent, "A and B or C". Remember that in
+this case, B must be a true value (not None, '', 0, [] or {}).
+
+::
+
+ #set $adj = $size > 1500 and 'large' or 'small'
+
+(Note: Cheetah's one-line {#if} will not work for this, since it
+produces output rather than setting a variable.
+
+You can also use the augmented assignment operators:
+
+::
+
+ ## Increment $a by 5.
+ #set $a += 5
+
+By default, {#set} variables are not visible in method calls or
+include files unless you use the {global} attribute: {#set global
+$var = EXPRESSION}. Global variables are visible in all methods,
+nested templates and included files. Use this feature with care to
+prevent surprises.
+
+#del
+----
+
+(inheritanceEtc.del)
+
+Syntax:
+
+::
+
+ #del $var
+
+{#del} is the opposite of {#set}. It deletes a { local} variable.
+Its usage is just like Python's {del} statement:
+
+::
+
+ #del $myVar
+ #del $myVar, $myArray[5]
+
+Only local variables can be deleted. There is no directive to
+delete a {#set global} variable, a searchList variable, or any
+other type of variable.
+
+#attr
+-----
+
+(inheritanceEtc.attr)
+
+Syntax:
+
+::
+
+ #attr $var = EXPR
+
+The {#attr} directive creates class attributes in the generated
+Python class. It should be used to assign simple Python literals
+such as numbers or strings. In particular, the expression must {
+not} depend on searchList values or {#set} variables since those
+are not known at compile time.
+
+::
+
+ #attr $title = "Rob Roy"
+ #attr $author = "Sir Walter Scott"
+ #attr $version = 123.4
+
+This template or any child template can output the value thus:
+
+::
+
+ $title, by $author, version $version
+
+If you have a library of templates derived from etexts
+(http://www.gutenberg.org/), you can extract the titles and authors
+and put them in a database (assuming the templates have been
+compiled into .py template modules):
+
+#def
+----
+
+(inheritanceEtc.def)
+
+Syntax:
+
+::
+
+ #def METHOD[(ARGUMENTS)]
+ #end def
+
+Or the one-line variation:
+
+::
+
+ #def METHOD[(ARGUMENTS)] : TEXT_AND_PLACEHOLDERS
+
+The {#def} directive is used to define new methods in the generated
+Python class, or to override superclass methods. It is analogous to
+Python's {def} statement. The directive is silent, meaning it does
+not itself produce any output. However, the content of the method
+will be inserted into the output (and the directives executed)
+whenever the method is later called by a $placeholder.
+
+::
+
+ #def myMeth()
+ This is the text in my method
+ $a $b $c(123) ## these placeholder names have been defined elsewhere
+ #end def
+
+ ## and now use it...
+ $myMeth()
+
+The arglist and parentheses can be omitted:
+
+::
+
+ #def myMeth
+ This is the text in my method
+ $a $b $c(123)
+ #end def
+
+ ## and now use it...
+ $myMeth
+
+Methods can have arguments and have defaults for those arguments,
+just like in Python. Remember the {$} before variable names:
+
+::
+
+ #def myMeth($a, $b=1234)
+ This is the text in my method
+ $a - $b
+ #end def
+
+ ## and now use it...
+ $myMeth(1)
+
+The output from this last example will be:
+
+::
+
+ This is the text in my method
+ 1 - 1234
+
+There is also a single line version of the {#def} directive. {
+Unlike the multi-line directives, it uses a colon (:) to delimit
+the method signature and body}:
+
+::
+
+ #attr $adj = 'trivial'
+ #def myMeth: This is the $adj method
+ $myMeth
+
+Leading and trailing whitespace is stripped from the method. This
+is in contrast to:
+
+::
+
+ #def myMeth2
+ This is the $adj method
+ #end def
+
+where the method includes a newline after "method". If you don't
+want the newline, add {#slurp}:
+
+::
+
+ #def myMeth3
+ This is the $adj method#slurp
+ #end def
+
+Because {#def} is handled at compile time, it can appear above or
+below the placeholders that call it. And if a superclass
+placeholder calls a method that's overridden in a subclass, it's
+the subclass method that will be called.
+
+#block ... #end block
+---------------------
+
+(inheritanceEtc.block)
+
+The {#block} directive allows you to mark a section of your
+template that can be selectively reimplemented in a subclass. It is
+very useful for changing part of a template without having to
+copy-paste-and-edit the entire thing. The output from a template
+definition that uses blocks will be identical to the output from
+the same template with the {#block ... #end block} tags removed.
+
+({ Note:} don't be confused by the generic word 'block'' in this
+Guide, which means a section of code inside { any} {#TAG ... #end
+TAG} pair. Thus, an if-block, for-block, def-block, block-block
+etc. In this section we are talking only of block-blocks.)
+
+To reimplement the block, use the {#def} directive. The magical
+effect is that it appears to go back and change the output text {
+at the point the original block was defined} rather than at the
+location of the reimplementation.
+
+::
+
+ #block testBlock
+ Text in the contents
+ area of the block directive
+ #if $testIt
+ $getFoo()
+ #end if
+ #end block testBlock
+
+You can repeat the block name in the {#end block} directive or not,
+as you wish.
+
+{#block} directives can be nested to any depth.
+
+::
+
+ #block outerBlock
+ Outer block contents
+
+ #block innerBlock1
+ inner block1 contents
+ #end block innerBlock1
+
+ #block innerBlock2
+ inner block2 contents
+ #end block innerBlock2
+
+ #end block outerBlock
+
+Note that the name of the block is optional for the {#end block}
+tag.
+
+Technically, {#block} directive is equivalent to a {#def} directive
+followed immediately by a {#placeholder} for the same name. In
+fact, that's what Cheetah does. Which means you can use
+{$theBlockName} elsewhere in the template to output the block
+content again.
+
+There is a one-line {#block} syntax analagous to the one-line
+{#def}.
+
+The block must not require arguments because the implicit
+placeholder that's generated will call the block without
+arguments.
+
+