This is the starter page for a collection of coding snippets for use in a zwiki. Please post comments and questions to GeneralDiscussion. (There's also the old DTMLCookbookDiscussion, but I think it's more about meta issues.)

cleanup

this page was renamed from ZwikiCookbook, but it's not just dtml.. rename back ? separate pages ? CookBook? ?

todo: replace live examples

List all pages with names beginning "HowTo..."

Here it's done in one line using a list comprehension:

<dtml-var "_.string.join([b.Title for b in pages() if b.Title.startswith('HowTo')], '<br>')">

_.string is the standard python string library.

pages() is Zwiki's fundamental wiki-searching method. It searches the [Catalog]?, for better scalability in large wikis, and returns a list of catalog brains which contain the frequently used page attributes like Title.

You can give it zcatalog-style search arguments, so we could search directly for pages with names beginning "HowTo", but zcatalog isn't always able to do wildcard matching so instead we search for all pages and filter the results ourselves.

startswith is a standard method of python string objects.

Look up a page object by name

<dtml-let page="pageWithName(pagename)">

Unlike pages(), this returns a real page object.

Include one page's content in another

Here's the easiest way:

<dtml-var "include('ThePage')">

which will fail silently if the page does not exist. Otherwise it is equivalent to:

<dtml-var "pageWithName('ThePage')(REQUEST=REQUEST,bare=1)">

That is,

  • get hold of the page object
  • call it so it renders itself
  • pass the bare argument so it doesn't add the usual skin
  • pass the REQUEST in case the user's current authentication is needed

Include a page's content in a page template

<div tal:content="structure python:here.include('ThePage')" />

In page templates called by Zwiki, here is the current wiki page.

Table of contents macro

Here is an old DTML+PythonScript macro that makes a fancy sort of ski-slope-colour-coded audience indicator and triple table of contents which I used on zwiki.org for a while. See eg QuickReference.

This only works for DTML-enabled wikis and requires manual maintenance of the contents entries and link targets, but less than if you did everything by hand. RestructuredText's .. contents:: directive is usually preferable nowadays. For more information see [http://custom-paper-writing.com/ custom paper]?.

## Script (Python) "toc"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=columns, headings=('Basics','Intermediate','Advanced'), colours=('green','red','black')
##title=
##

linkindex = 1
print """
<!-- toc macro start -->
<table border="0" width="" align="center">
  <tr>
"""
columnwidth = '' #100/len(columns)
colindex = 0
for column in columns:
    print """
    <td valign="top" width="%s%%">
    """ % (columnwidth)
    if column == None or column == 0:
        print """
            &nbsp;
        """
    else:
        heading, colour = headings[colindex], colours[colindex]
        print """
      <div style="color:white; background-color:%s; font-weight:bold;
                  text-align:center;padding-left:1em;padding-right:1em;">%s</div>
      <div class="pagecontents" style="font-size:small;">
        <table>
          <tr>
            <td valign="top">
            <ol style="margin-top:0; margin-bottom:0; margin-right:2em;" class="subtext" start="%s">
        """ % (colour,heading,linkindex)#colour,colour,linkindex)
        if column != 1:
            for link in column:
                print """
                      <li><a href="#%s">%s</a></li>
                """ % (linkindex,link)
                linkindex += 1
        print """
              </ol>
            </td>
          </tr>
        </table>
      </div>
    </td>
        """
    colindex += 1
print """
  </tr>
</table>
<!-- toc macro end -->
"""
return printed

Install this as a pythonscript with id toc in the ZODB, then call it at the top of any DTML-enabled wiki page like this:

<dtml-var "toc((['basic topic 1','basic topic 2'],
                ['intermediate topic'],
                ['advanced topic'],
                ))">

The links point to #1, #2, etc. and you need to create those named anchors at the start of each corresponding section of the page. You could also do this:

<dtml-var "toc(([],None,None))">

or override the column headings and colours. The layout may or may not work as well in the plone skin.

Get zope memory usage

Install this as an ExternalMethod with id memusage:

def memusage(self):
  """
  Get this process's memory usage.
  """
  # method 1
  # may not work on virtual private servers
  import resource
  usage = resource.getrusage(resource.RUSAGE_SELF)[2]
  if usage > 0: return usage

  # method 2
  # requires a unix-style ps command
  # may fail in low memory situations
  import os
  try: return int(os.popen('ps h -o vsize %s'%os.getpid()).read())
  except: return 0

then you could display it with <dtml-var memusage>. See WikiStats, MemoryUsage.

Generate colours and progress bars

This generates a green-red gradient, useful for a memory usage indicator:

<dtml-in "[0,10,20,30,40,50,60,70,80,90,100]" prefix=x>
<dtml-let
test="x_sequence_item*1000"
mem="test #memusage()[2]"
max="100000"
usage="_.int(mem/(max/100))"
free="100-usage"
r="221+usage/3"
g="250-usage*usage/40"
b="250-usage*usage/40"
colour="'#%02x%02x%02x'%(r,g,b)"
m="(usage>30)*255"
fontcolour="'#%02x%02x%02x'%(m,m,m)"
>
<small>
<table border=0 cellpadding=0 cellspacing=0 width="100%">
<tr>
<td width="&dtml-usage;%" bgcolor="&dtml-colour;" style="color:&dtml-fontcolour;;">
<b>memory usage: &dtml-mem; (&dtml-usage;%)</b>
</td>
<td width="&dtml-free;%" >
&nbsp;
</td>
</tr>
</table>
</small>
</dtml-let>
</dtml-in>

See ColourTests for more.

Zwiki issue tracker maintenance

Here are some things you can do at the zopectl debug prompt (see ZopeWiki:DebuggingZope for more about this).

Recategorize a number of issues:

>>> t = app.wikifolder.anypage
>>> change = lambda num,cat: t.issuePageWithNumber(num).changeIssueProperties(category=cat)
>>> [change(n,'newcategory') for n in [23,101,42]]
>>> get_transaction().commit()

Recategorize a whole category, without sending mail:

>>> t = app.wikifolder.anypage
>>> def change(old,new):
...   for p in t.pages(category=old):
...     p.getObject().category=new
...     p.getObject().index_object()
...
>>> change('oldcategory','newcategory')
>>> get_transaction().commit()