Hello,

I wasn't happy with two things about SQLTABLE :

A) How you are obliged to show the id field if you want linkto
functionality. Not only do I not always want the user to see that id
field (they may use a different identifier, or it may simply confuse
them), I would also rather be able to label the link with 'edit',
'approve' or 'delete' etc... and preferably have as many options as I
want.

B) How it generates hyperlinks for all fields of type 'reference', as
opposed to just the id field. I was about to submit this as a bug
until I checked the code and saw it was done on purpose. The reason it
seems wrong to me is that the function I would typically supply as the
linkto argument is designed to handle records from the table from
which SQLTABLE was generated, and not records from one of the
referenced tables, yet the generated hyperlink creates a URL to that
function passing an id from the referenced table, which is dangerous
if that's not what was intended. There also doesn't seem to be a way
to escape this behaviour if I want to use linkto functionality.

So I set out to change SQLTABLE to have an optional argument:
linkColumns, which takes a list/tuple of format [(ColumnHeaderText,
Function, LinkText), ...].

This adds columns to the right of the table with links to which the id
of the record in that row will be passed.
With this you can skip the linkto argument, and if you specify columns
in the columns args you can avoid showing the id (although it needs to
be included in the first argument: sqlrows), so it becomes trivial to
generate a table like so:

Micky Mouse     Disney       $15,000       [edit]      [show
photos]      [archive]     [delete]
Donald Duck      Disney       $18,000       [edit]      [show
photos]      [archive]     [delete]

It works just the way I want it and doesn't interfere with the normal
functioning of SQLTABLE, as far as I can tell (although I had to move
linkColumns=None to the end of the argument list as it would otherwise
go wrong when the appadmin's database adminstration page called
it...It seemed to be explicitly naming linkColumns in the arguments,
which is strange...)

I'm pretty pleased with this, I've never extended an open-source
framework's functionality before, and was wondering whether it should
be included in web2py?
I've listed the 3 changes to sqlhtml.py below, I think the only
additional steps needed is for someone to go test it and make sure I'm
not doing anything daft.
Perhaps some users would also prefer if the LinkText argument could
accept something similar to the format string used in field
definitions, i.e. "%(another_column_name_used_in_the_row)s"...

Changes to sqlhtml.py (I'm on version 1.93.2):

>>>>>>>>>>>> circa line 1264:

def __init__(
        self,
        sqlrows,
        linkto=None,
        upload=None,
        orderby=None,
        headers={},
        truncate=16,
        columns=None,
        th_link='',
        linkColumns=None,
        **attributes
        ):

>>>>>>>>>>>> circa line 1296:

        if headers!=None:
            for c in columns:
                if orderby:
                    row.append(TH(A(headers.get(c, c),
                                    _href=th_link+'?orderby=' + c)))
                else:
                    row.append(TH(headers.get(c, c)))
            if linkColumns:
                for lc in linkColumns:
                    row.append(TH(lc[0]))
            components.append(THEAD(TR(*row)))

        tbody = []

>>>>>>>>>>>> circa line 1390:

            if linkColumns:
                if not record.has_key('id'):
                    raise SyntaxError, 'Sqlrows must include the id
field when the linkColumns argument is specified in SQLTABLE()'
                for lc in linkColumns:
                    # Not sure why I need a try catch here...
                    try:
                        href = lc[1](record.id, 'table', tablename)
                    except TypeError:
                        href = '%s/%s/%s' % (linkto, tablename,
record.id)
                    r = A(lc[2], _href=href)
                    row.append(TD(r))

Reply via email to