6. Developing Custom Tags

#
6. Developing Custom Tags

In most complex applications you are likely to encounter presentation problems which the standard collection of tags cannot easily solve. Albatross provides a set of classes in the `albatross.template` module which are designed to allow the development of custom tags.

The `albatross` module performs `from template import *` so all contents of `albatross.template` are available in `albatross`.

The following is a simple calendar tag which formats a single month like the unix cal(1) program.

    import time
    import calendar
    import albatross

    class Calendar(albatross.EmptyTag):

        name = 'alx-calendar'

        def to_html(self, ctx):
            year = self.get_attrib('year')
            if year is not None:
                year = ctx.eval_expr(year)
            month = self.get_attrib('month')
            if month is not None:
                month = ctx.eval_expr(month)
            if month is None or year is None:
                now = time.localtime(time.time())
                if year is None:
                    year = now[0]
                if month is None:
                    month = now[1]
            ctx.write_content('<table>\n')
            ctx.write_content('<tr align="center"><td colspan="7">%s %s</td></tr>\n' \
                              % (calendar.month_name[month], year))
            ctx.write_content('<tr>')
            for i in range(7):
                ctx.write_content('<td>%s</td>' \
                                  % calendar.day_abbr[(i + 6) % 7][:2])
            ctx.write_content('</tr>\n')
            calendar.setfirstweekday(6)
            for r in calendar.monthcalendar(year, month):
                ctx.write_content('<tr align="right">')
                for i in range(7):
                    if r[i]:
                        ctx.write_content('<td>%s</td>' % r[i])
                    else:
                        ctx.write_content('<td></td>')
                ctx.write_content('</tr>\n')
            ctx.write_content('</table>\n')

To use the tag in your application you must make the class available to the execution context. If you are using an Albatross application object you can do this by passing the class to the `register_tagclasses()` method of the application object.

    from albatross import SimpleApp

    app = SimpleApp('ext.py', '.', 'start')
    app.register_tagclasses(Calendar)

All Albatross application classes inherit from the `ResourceMixin` in the `albatross.context` module. Execution contexts which are used with application objects inherit from the `AppContext` class from the `albatross.app` module which automatically retrieves all resources from the parent application object.

If you are using the `SimpleContext` class for your execution context then you will need to call the `register_tagclasses()` method of the execution context immediately after construction.

The following is an example template file which uses the `<alx-calendar>` tag.

    <html>
    <head><title>Calendar for <al-value expr="year"></title></head>
    <body>
    <h1>Calendar for <al-value expr="year"></h1>
    <table cellpadding="10">
    <al-for iter="r" expr="range(1,13)" cols="3" flow="across">
     <tr valign="top">
     <al-for iter="m" expr="r.value()">
      <td><alx-calendar month="m.value()" year="year"></td>
     </al-for>
     </tr>
    </al-for>
    </table>
    </body>
    </html>

A complete program which uses this extension tag and template file can be found in the `samples/extension` directory. Use the `install.py` script to install the sample.

    cd samples/extension
    python install.py