[Zope] dtml-in batching improved

Ivo van der Wijk ivo@amaze.nl
Thu, 31 May 2001 18:40:14 +0200


Hi all,

I'm reposting this here as I think this is of interest to non-developers
as well, and I don't get much response on zope-dev anyway :)

When using batching in dtml-in, why is 'previous-sequence' only defined at
the first iteration of the current batch? And why is 'next-sequence' only 
defined at the last iteration of the current batch?

This behaviour makes it difficult to display a batch like this:

-- begin sample --
Item N
Item N+1
Item N+2

(link to previous items)  (link to next items)
-- end sample --

Because the code would be something like:

-- begin sample --
<dtml-in something start=query_start size=3>

  [do something with sequence-item]

  <dtml-if sequence-end> <!-- check if last item of batch -->
    <dtml-if previous-sequence>
      (link to previous items)
    </dtml-if>
    <dtml-if next-sequence>
      (link to next items)
    </dtml-if>
  </dtml-if>
</dtml-in>
-- end sample --

However, if your batchsize is larger than 1, 'previous-sequence' will always
be untrue at the last item (when sequence-item is true).

The only solution would be implement a second dtml-in after the first one
purely for displaying the previous link.

Also, dtml-in would re-execute your "expr" (which it does not very efficiently),
so if you want to avoid doing the "expr" twice, you'd have to store it 
temporarily using dtml-let (or my dtml-set tag ;).

The end result would be:

-- start sample --

<dtml-let foo="expr">
 <dtml-in foo start=start_query size=3>
   [do something with sequence-item]
 </dtml-in>
 <dtml-in foo start=start_query size=3>
  <!-- code below is safe, as the variables are only true at the resp. top and 
       end, though the truly paranoid could check for sequence-start / -end  

       patch #1 below would break such code!
  -->
  <dtml-if sequence-end>                
    <dtml-if previous-sequence>
      (link to previous items)
    </dtml-if>
    <dtml-if next-sequence>
      (link to next items)
    </dtml-if>
  </dtml-if>
 </dtml-in>
</dtml-let>

-- end sample --

And at this point I really would start to implement the batching myself in
python :)
 
Of course, basically the same applies if you want both the previous/next link
at the top of the batch display.

(Imagine you want both! :)

Either I'm missing something really obvious here, or the patches below make
sense. There are two versions:

- patch #1: This version fixes the issue above by enabling the values of 
previous/next-sequence throughout the entire batch (and other
related variables as well: X-sequence, X-sequence-start-index, 
X-sequence-end-index, X-sequence-size) (which may break existing sites), and

- patch #2: This version introduces new variablenames, leaving the behaviour of
previous/next-sequence.

A third alternative would be to only define the variables at the top and
bottom of the batch.

Both versions fix (I think) a grammatical error.

It's up to the DC guys if they feel like incorporating either of these patches
in a next release :)

patch #1: define variables everywhere in the batch

This patch makes sure that the following variables are available through
each iteration of dtml-in, for each item.

!!!!! This patch may break alot of dtml code !!!!!!

next-sequence
next-sequence-start-index
next-sequence-end-index
next-sequence-size
previous-sequence
previous-sequence-start-index
previous-sequence-end-index
previous-sequence-size

-- patch begins here --

*** Zope-2.3.2-orig/lib/python/DocumentTemplate/DT_In.py        Fri Apr 13 21:30:38 2001
--- Zope-2.3.2-src/lib/python/DocumentTemplate/DT_In.py Tue May 29 19:52:36 2001***************
*** 583,611 ****
                  for index in range(first,end):
                      # preset
                      kw['previous-sequence']= 0
!                     kw['next-sequence']= 0 # now more often defined then previously
                      #
!                     if index==first or index==last:
!                         # provide batching information
!                         if first > 0:
!                             pstart,pend,psize=opt(0,first+overlap,
!                                                   sz,orphan,sequence)
!                             if index==first: kw['previous-sequence']=1
!                             kw['previous-sequence-start-index']=pstart-1
!                             kw['previous-sequence-end-index']=pend-1
!                             kw['previous-sequence-size']=pend+1-pstart
!                         try:
!                             # The following line is a sneaky way to
!                             # test whether there are more items,
!                             # without actually computing a length:
!                             sequence[end]
!                             pstart,pend,psize=opt(end+1-overlap,0,
!                                                   sz,orphan,sequence)
!                             if index==last: kw['next-sequence']=1
!                             kw['next-sequence-start-index']=pstart-1
!                             kw['next-sequence-end-index']=pend-1
!                             kw['next-sequence-size']=pend+1-pstart
!                         except: pass
          
                      if index==last: kw['sequence-end']=1
  
--- 583,610 ----
                  for index in range(first,end):
                      # preset
                      kw['previous-sequence']= 0
!                     kw['next-sequence']= 0 # now more often defined than previously
                      #
!                     # provide batching information
!                     if first > 0:
!                         pstart,pend,psize=opt(0,first+overlap,
!                                               sz,orphan,sequence)
!                         kw['previous-sequence']=1
!                         kw['previous-sequence-start-index']=pstart-1
!                         kw['previous-sequence-end-index']=pend-1
!                         kw['previous-sequence-size']=pend+1-pstart
!                     try:
!                         # The following line is a sneaky way to
!                         # test whether there are more items,
!                         # without actually computing a length:
!                         sequence[end]
!                         pstart,pend,psize=opt(end+1-overlap,0,
!                                               sz,orphan,sequence)
!                         kw['next-sequence']=1
!                         kw['next-sequence-start-index']=pstart-1
!                         kw['next-sequence-end-index']=pend-1
!                         kw['next-sequence-size']=pend+1-pstart
!                     except: pass
          
                      if index==last: kw['sequence-end']=1
  
-- end --

patch #2: introduce new variables

This patch introduces the variables

batch-next-sequence
batch-next-sequence-start-index
batch-next-sequence-end-index
batch-next-sequence-size
batch-previous-sequence
batch-previous-sequence-start-index
batch-previous-sequence-end-index
batch-previous-sequence-size

Which behave exactly the same as the variables withouth 'batch-' in front,
but these are available with each iteration/item of dtml-in, not just the
first/last. This patch should not break any existing dtml code.

-- patch begins here --

*** Zope-2.3.2-orig/lib/python/DocumentTemplate/DT_In.py	Fri Apr 13 21:30:38 2001
--- Zope-2.3.2-src/lib/python/DocumentTemplate/DT_In.py	Tue May 29 20:23:24 2001
***************
*** 583,589 ****
                  for index in range(first,end):
                      # preset
                      kw['previous-sequence']= 0
!                     kw['next-sequence']= 0 # now more often defined then previously
                      #
                      if index==first or index==last:
                          # provide batching information
--- 583,609 ----
                  for index in range(first,end):
                      # preset
                      kw['previous-sequence']= 0
!                     kw['next-sequence']= 0 # now more often defined than previously
!                     # provide batching information
!                     if first > 0:
!                         pstart,pend,psize=opt(0,first+overlap,
!                                               sz,orphan,sequence)
!                         kw['batch-previous-sequence']=1
!                         kw['batch-previous-sequence-start-index']=pstart-1
!                         kw['batch-previous-sequence-end-index']=pend-1
!                         kw['batch-previous-sequence-size']=pend+1-pstart
!                     try:
!                         # The following line is a sneaky way to
!                         # test whether there are more items,
!                         # without actually computing a length:
!                         sequence[end]
!                         pstart,pend,psize=opt(end+1-overlap,0,
!                                               sz,orphan,sequence)
!                         kw['batch-next-sequence']=1
!                         kw['batch-next-sequence-start-index']=pstart-1
!                         kw['batch-next-sequence-end-index']=pend-1
!                         kw['batch-next-sequence-size']=pend+1-pstart
!                     except: pass
                      #
                      if index==first or index==last:
                          # provide batching information
--

To apply either of them, cd to your SOFTWARE_HOME (i.e. Zope-2.3.2-src)
and patch -p1 < /location/of/patch

NOTE! It only makes sense to apply one of these patches, not both!

Cheers,

	Ivo

-- 
Drs. I.R. van der Wijk                              -=-
Brouwersgracht 132                      Amaze Internet Services V.O.F.
1013 HA Amsterdam                                   -=-
Tel: +31-20-4688336                          Linux/Web/Zope/SQL
Fax: +31-20-4688337                           Network Solutions
Web:     http://www.amaze.nl/                    Consultancy
Email:   ivo@amaze.nl                               -=-