AidanLee has asked for the wisdom of the Perl Monks concerning the following question:

I have been using the Template Toolkit for a while now and have come across some issues. I was wondering if anyone else had similar experiences, and if there is anything to be done about them aside from contacting the Module's authors.

The application I am working uses the toolkit to, among other things, format a list of records pulled from a database. The dilemma is that with caching enabled (the default state) when the number of entries pulled from the database varies, the change is not reflected in the resulting output. This was confusing, as I'd expect caching to only affect the template itself, and that the placeholders in the templates would be populated anew each time. I tried to enable template compiling with similar results.

As an aside on this journey, for some reason my templates only get re-processed when I change the source code file calling the template. It does not seem to check if the original template file has changed (this is for caching. I did not check for compiling).

Continuing on, while I wanted very much to use caching, I decided that I should try to disable caching to see if the updates to the database would then be reflected in the templates. so i dutifully said:

my $template = Template->new({INCLUDE_PATH => 'e:/web_projects/marksphotos/templates/',DELIMITER=>';',CACHE_SIZE=>0});

To which I got the less than gratifying response:

Undefined subroutine &Template::Service::confess called at c:/Perl/site/lib/Template/Service.pm line 183.

I was running toolkit v2.0. I checked the website and found that 2.02 was out. I dutifully downloaded and installed the upgrade, and tried again, with the disabled cache. Now I get:

Not a GLOB reference at c:/Perl/site/lib/Template/Provider.pm line 506.

Is anyone aware of anything like this, or should I take it up with the Module authors? I will post source if requested. FYI, I am using ActiveState Build 616 on Win32. This is a 5.6.0 build.

Replies are listed 'Best First'.
Re: Template Toolkit and Caching
by Masem (Monsignor) on May 20, 2001 at 08:54 UTC
    I think we need to see what your template code looks like, as well as an appropriate snippet of code in which you prepare to populate the template. IT's hard to venture why the caching is behaving as such.


    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain

      Ok, Templates first. Here's the main template being called, list.t:

      [% WRAPPER 'pagebase.t' title="| Mark's Log" %] <div style="position:absolute;top:80px;left:10px;width:600px"> <h2>Mark's Log</h2> [% WRAPPER 'listbase.t' view='log' %] [% IF list.offset == 0 %] [% INCLUDE 'log/entry.t' log = entries.shift %] <div class="header">past log entries ...</div> [% END %] [% FOREACH log = entries %] [% r = text.crop(log.Body,200) log.Body = r.0 log.cropped = r.1 %] [% INCLUDE 'log/entry.t' %] [% END %] [% END %] </div> [% END %]

      here is entry.t, which is called for each item in the entries array:

      <h3> [% log.Subject %]<br /> <span class="date"> [% log.Date_Added %] </span> </h3> <p class="log"> [% text.nl2br(log.Body) %] [% IF log.cropped == 1 %] <span class="more" > [ <a href="details.cgi?view=log&id=[% log.ID %]"> more +...</a> ] </span> [% END %] </p> [% IF log.Date_Added != log.Date_Modified %] <p class="revision">last revised [% log.Date_Modified %]</p> [% END %]

      here is listbase.t, a wrapper which handles displaying the list count and prev/next buttons:

      <hr /><p class="more" >[% view %] [% list.offset + 1 %] - [% IF +list.offset + list.limit < list.total %][% list.offset + list.limit % +][% ELSE %][% list.total %][% END %] of [% list.total %]</p> [% content %] <hr /> <p class="more" > [% IF list.offset > 0 %] [ &lt; <a href="index.cgi?view=[% view %]&offset=[% list.off +set - list.limit %]"> previous [% list.limit %]</a> ] [% END %] [% IF list.offset + list.limit < list.total %] [ <a href="index.cgi?view=[% view %]&offset=[% list.offset + + list.limit %]">next [% list.limit %] </a>&gt; ] [% END %] </p>

      and here is pagebase.t, a wrapper which controls the overall html page layout:

      Content-Type: text/html; charset=UTF-8 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w +3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www/w3/org/TR/xhtml1" xml:lang="en-us"> <head> <title>Mark M. Tanny, Photographer [% title %]</title> <link rel="stylesheet" href="site.css" title="site wide style sh +eet" /> </head> <body> <div id="title" class="header" style="text-align:right;position: +absolute;top:30px;left:10px;width:600px;"> <a href="index.cgi?view=collections">Photo Collections</a> | <a href="index.cgi?view=log">Mark's Log</a> </div> [% content %] </body> </html>

      and here's the script that calls list.t Still a little rough around the edges. Just so you know, $params{view} equals 'log' in this trial. A little rough around the edges still:

      #------------------------------------- # PRAGMAS use lib 'e:/web_projects/marksphotos/lib'; use strict; use utf8; #------------------------------------- # IN HOUSE MODULES #use Config; use HTML::Tools; use dbWrapper qw( QueryDB ); #------------------------------------- # 3RD PARTY MODULES use Template; #===================================================================== +===== # MAIN #===================================================================== +===== my %params = ParseQueryString(); my $template = Template->new({INCLUDE_PATH => 'e:/web_projects/marksph +otos/templates/',DELIMITER=>';',CACHE_SIZE=>0}); my %db_info = (); my $page = ''; for( $params{view} ) { /log/ and do { $db_info{fields} = ['ID','Date_Added','Da +te_Modified','Subject','Body']; $db_info{table} = 'LogEntries'; $db_info{fieldnames} = $db_info{fields}; $db_info{count_table} = 'LogEntries'; $page = 'log/list.t'; last; }; /announcements/ and do { $db_info{fields} = ['ID','Date_Added','Da +te_Modified','Body']; $db_info{table} = 'Announcements'; $db_info{fieldnames} = $db_info{fields}; $db_info{count_table} = 'Announcements'; $page = 'announcements/list.t'; last; }; /collections/ and do { $db_info{fields} = ['C.ID','C.Date_Added' +,'C.Date_Modified','C.Title','C.Summary','P.Filename as Image']; $db_info{table} = 'PhotoCollections C LEF +T JOIN Photos P ON C.Feature_Image = P.ID'; $db_info{fieldnames} = [ 'ID','Date_Added +','Date_Modified','Title','Summary','Image' ]; $db_info{count_table} = 'PhotoCollections +'; $page = 'collections/list.t'; last; }; do{ print FrontPage(); exit(0); }; } #------------------------------------- my $list_limit = ( exists $params{limit} and $params{limit} =~ /^(\d ++)$/ ) ? $1 : 10; my $list_offset = ( exists $params{offset} and $params{offset} =~ /^(\ +d+)$/ ) ? $1 : 0; #------------------------------------- if( $db_info{table} ) { my $sth = undef; #-- sanity check for any available records ---------------------- { $sth = QueryDB("SELECT COUNT(ID) from ".$db_info{count_table}." WH +ERE Published='1'"); } my( $count ) = $sth->fetchrow_array; if( $count > 0 ) #-- there are records to fetch ---------------------------------- { if( $count > $list_offset ) #-- fetching a set of records in a valid range ----------------- +- { $sth = QueryDB("SELECT ".join(',',@{$db_info{fields}})." FRO +M ".$db_info{table}." WHERE Published='1' ORDER BY Date_Added DESC LI +MIT $list_offset,$list_limit"); my($arrayref,%hash) = ( undef ); push @{$arrayref},{ %hash } while( @hash{ @{$db_info{fieldna +mes}} } = $sth->fetchrow_array() ); #-- successfully retrieved records ------------------------- +----- if( scalar( @{$arrayref} ) ) { my $result = ''; $template->process($page,{entries=>$arrayref, list => { limit=>$list_limit, offset=>$list_offset +, total=>$count }, text => { crop => \&crop_text, nl2br => \&nl2br } }, \$result ) or die $template->error(); print $result,$count and exit(0); } else #-- couldn't retrieve records ------------------------------ +----- { print ErrorMessage("There has been an internal error") a +nd exit(0); } } else #-- tried to get set of records off the end of the table ------- +- { print ErrorMessage("You've tried to get a list of entries t +hat don't exist") and exit(0); } } else #-- there aren't any records to fetch --------------------------- { print ErrorMessage("There are no entries for display") and exit +(0); } } #===================================================================== +===== # SUBS #===================================================================== +===== sub FrontPage { return ErrorMessage("welcome to the front page"); } sub ErrorMessage { my $text = ''; $template->process('error.t',{message=>$_[0]},\$text ) or die $tem +plate->error(); return $text; } #===================================================================== +===== sub crop_text #a second return value of '1' indicates that the string was truncated. { my($text,$limit) = @_; $text =~ /^(.{1,$limit}\W)/s; return ($text,0) if( $text eq $1 ); return ($1,1); } # convert newlines to line breaks sub nl2br { my $text = $_[0]; $text =~ s|\n|<br />|g; return $text }
Re: Template Toolkit and Caching
by koolade (Pilgrim) on May 20, 2001 at 19:33 UTC

    Have you tried posting the question to the Template Toolkit mailing list? Somebody may have an answer here on PM, but you might have better luck on the mailing list. Info on subscribing can be found at http://www.tt2.org/info.html#lists