From: richard Date: Fri, 26 Mar 2004 01:10:19 +0000 (+0000) Subject: *** empty log message *** X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=a43a63a0e74efd202cbc76bb6a1cf561430b31b7;p=roundup.git *** empty log message *** git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@2200 57a73879-2fb5-44c3-a270-3262357dd7e2 --- diff --git a/doc/templating.txt b/doc/templating.txt index 0a750d9..940ae01 100644 --- a/doc/templating.txt +++ b/doc/templating.txt @@ -1,359 +1,6 @@ -========================== -HTML Templating Mechanisms -========================== +========================= +Roundup Tracker Templates +========================= -:Version: $Revision: 1.14 $ - -Current Situation and Issues -============================ - -Syntax ------- - -Roundup currently uses an element-based HTML-tag-alike templating syntax:: - - - -The templates were initially parsed using recursive regular expression -parsing, and since no template tag could encapsulate itself, the parser -worked just fine. Then we got the ```` tag, which could have other -```` tags inside. This forced us to move towards a more complete -parser, using the standard python sgmllib/htmllib parser. The downside of this -switch is that constructs of the form:: - - "> - -don't parse as we'd hope. We can modify the parser to work, but that doesn't -another couple of issues that have arisen: - -1. the template syntax is not well-formed, and therefore is a pain to parse - and doesn't play well with other tools, and -2. user requirements generally have to be anticipated and accounted for in - templating functions (like ``plain()`` and ``checklist()`` above), and - we are therefore artificially restrictive. - -Arguments for switching templating systems: - -*Pros* - - - more flexibility in templating control and content - - we can be well-formed - -*Cons* - - - installed user base (though they'd have to edit their templates with the - next release anyway) - - current templating system is pretty trivial, and a more flexible system - is likely to be more complex - - -Templates ---------- - -We should also take this opportunity to open up the flexibility of the -templates through: - -1. allowing the tracker to define a "page" template, which holds the overall - page structure, including header and footer - - - -Possible approaches -=================== - -Zope's PageTemplates --------------------- - -Using Zope's PageTemplates seems to be the best approach of the lot. -In my opinion, it's the peak of HTML templating technology at present. With -appropriate infrastructure, the above two examples would read: - - status checklist - - - -... which doesn't look that much more complicated... honest... - -Other fun can be had when you start playing with stuff like: - - - - - - - -
- mailto link - subjectreceived date
- -Note: even if we don't switch templating as a whole, this document may be -applied to the ZRoundup frontend. - -PageTemplates in a Nutshell -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -PageTemplates consist of three technologies: - -TAL - Template Attribute Language - This is the syntax which is woven into the HTML using the ``tal:`` tag - attributes. A TAL parser pulls out the TAL commands from the attributes - runs them using some expression engine. - -TALES - TAL Expression Syntax - The expression engine used in this case is TALES, which runs the expressions - that form the tag attribute values. TALES expressions come in three - flavours: - - Path Expressions - eg. ``item/status/checklist`` - These are object attribute / item accesses. Roughly speaking, the path - ``item/status/checklist`` is broken into parts ``item``, ``status`` - and ``checklist``. The ``item`` part is the root of the expression. - We then look for a ``status`` attribute on ``item``, or failing that, a - ``status`` item (as in ``item['status']``). If that - fails, the path expression fails. When we get to the end, the object we're - left with is evaluated to get a string - methods are called, objects are - stringified. Path expressions may have an optional ``path:`` prefix, though - they are the default expression type, so it's not necessary. - - String Expressions - eg. ``string:hello ${user/name}`` - These expressions are simple string interpolations (though they can be just - plain strings with no interpolation if you want. The expression in the - ``${ ... }`` is just a path expression as above. - - Python Expressions - eg. ``python: 1+1`` - These expressions give the full power of Python. All the "root level" - variables are available, so ``python:item.status.checklist()`` would be - equivalent to ``item/status/checklist``, assuming that ``checklist`` is - a method. - -PageTemplates - The PageTemplates module glues together TAL and TALES. - - -Implementation -~~~~~~~~~~~~~~ - -I'm envisaging an infrastructure layer where each template has the following -"root level" (that is, directly accessible in the TALES namespace) variables -defined: - -*klass* - The current class of item being displayed as an HTMLClass instance. Name is - mangled so it can be used in Python expressions. - -*item* - The current item from the database, if we're viewing a specific item, as an - HTMLItem instance. If it doesn't exist, then we're on a new item page. - -(*classname*) - this is one of two things: - - 1. the *item* is also available under its classname, so a *user* item - would also be available under the name *user*. This is also an HTMLItem - instance. - 2. if there's no *item* then the current class is available through this - name, thus "user/name" and "user/name/menu" will still work - the latter - will pull information from the form if it can. - - this is a dangerous attribute, and may cause us pain the long run (its name - may clash with other top-level variables ... it already clashed with the - proposed *user* variable). It might be safer to go with just *class* and - *item*, actually... - -*form* - The current CGI form information as a mapping of form argument name to value - -*request* - Includes information about the current request, including: - - the url - - the current index information (``filterspec``, ``filter`` args, - ``properties``, etc) parsed out of the form. - - methods for easy filterspec link generation - - *user*, the current user item as an HTMLItem instance - -*tracker* - The current tracker - -*db* - The current open database - -*config* - The current instance config - -*modules* - python modules made available (XXX: not sure what's actually in there tho) - -Accesses through a class (either through *klass* or *db.*):: - - class HTMLClass: - def __getattr__(self, attr): - ''' return an HTMLItem instance ''' - def classhelp(self, ...) - def list(self, ...) - def filter(self): - ''' Return a list of items from this class, filtered and sorted - by the current requested filterspec/filter/sort/group args - ''' - -Accesses through an *item*:: - - class HTMLItem: - def __getattr__(self, attr): - ''' return an HTMLItem instance ''' - def history(self, ...) - def remove(self, ...) - -Note: the above could cause problems if someone wants to have properties -called "history" or "remove"... - -String, Number, Date, Interval HTMLProperty - a wrapper object which may be stringified for the current plain() behaviour - and has methods emulating all the current display functions, so - ``item/name/plain`` would emulate the current ``call="plain()``". Also, - ``python:item.name.plain(name=value)`` would work just fine:: - - class HTMLProperty: - def __init__(self, instance, db, ...) - def __str__(self): - return self.plain() - - class StringHTMLProperty(HTLProperty): - def plain(self, ...) - def field(self, ...) - def stext(self, ...) - def multiline(self, ...) - def email(self, ...) - - class NumberHTMLProperty(HTMLProperty): - def plain(self, ...) - def field(self, ...) - - class BooleanHTMLProperty(HTMLProperty): - def plain(self, ...) - def field(self, ...) - - class DateHTMLProperty(HTMLProperty): - def plain(self, ...) - def field(self, ...) - def reldate(self, ...) - - class IntervalHTMLProperty(HTMLProperty): - def plain(self, ...) - def field(self, ...) - def pretty(self, ...) - -Link HTMLProperty - the wrapper object would include the above as well as being able to access - the class information. Stringifying the object itself would result in the - value from the item being displayed. Accessing attributes of this object - would result in the appropriate entry from the class being queried for the - property accessed (so item/assignedto/name would look up the user entry - identified by the assignedto property on item, and then the name property of - that user):: - - class LinkHTMLProperty(HTMLProperty): - ''' Be a HTMLItem too ''' - def __getattr__(self, attr): - ''' return a new HTMLProperty ''' - def download(self, ...) - def checklist(self, ...) - -Multilink HTMLProperty - the wrapper would also be iterable, returning a wrapper object like the Link - case for each entry in the multilink:: - - class MultilinkHTMLProperty(HTMLProperty): - def __len__(self): - ''' length of the multilink ''' - def __getitem(self, num): - ''' return a new HTMLItem ''' - def checklist(self, ...) - def list(self, ...) - -*request* - the request object will handle:: - - class Request: - def __init__(self, ...) - def filterspec(self, ...) - -Accesses through the *user* attribute of *request*:: - - class HTMLUser(HTMLItem): - def hasPermission(self, ...) - -(note that the other permission check implemented by the security module may - be implemented easily in a tal:condition, so isn't needed here) - -Template files -~~~~~~~~~~~~~~ - -Each instance will have the opportunity to supply the following templates: - -page - This is the overall page look template, and includes at some point a TAL - command that includes the variable "content". This variable causes the actual - page content to be generated. - -[classname].[template type] - Templates that have this form are applied to item data. There are three forms - of special template types: - - [classname].index - This template is used when the URL specifies only the class, and not an item - designator. It displays a list of [classname] items from the database, and - a "filter refinement" form. - Would perform a TAL ``repeat`` command using the list supplied by - ``class/filter``. This deviates from the current situation in that currently - the index template specifies a single row, and the filter part is - automatically generated. - - [classname].item - This template is used when the URL specifies an item designator. It's the - default template used (when no template is explicitly given). It displays - a single item from the database using the *classname* variable (that - is, the variable of the same name as the class being displayed. If - - These two special template types may be overridden by the :template CGI - variable. - -Note that the "newitem" template doesn't exist any more because the item -templates may determine whether the page has an existing item to render. The -new item page would be accessed by "/tracker/url/issue?:template=item". -The old "filter" template has been subsumed by the index template. - - -Integrating Code -~~~~~~~~~~~~~~~~ - -We will install PageTemplates, TAL and ZTUtils in site-packages. If there is a -local Zope installation, it will use its own PageTemplates code (Zope modifies -the module search path to give precedence to its own module library). - -We will then install the trivial MultiMapping and ComputedAttribute modules in -the Roundup package, and have some import trickery that determines whether -they are required, and if so they will be imported as if they were at the -"top level" of the module namespace. - -New CGI client structure -~~~~~~~~~~~~~~~~~~~~~~~~ - -Handling of a request in the CGI client will take three phases: - -1. Determine user, pre-set "content" to authorisation page if necessary -2. Render main page, with callback to "content" -3. Render content - if not pre-set, then determine which content to render - - -Use Cases -~~~~~~~~~ - -Meta/parent bug - Can be done with addition to the schema and then the actual parent heirarchy - may be displayed with a new template page ":dependencies" or something. - -Submission wizard - Can be done using new templates ":page1", ":page2", etc and some additional - actions on the CGI Client class in the instance. +:Version: $Revision: 1.15 $