diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py
index 5ab54c73..b37e6b93 100644
--- a/gluon/sqlhtml.py
+++ b/gluon/sqlhtml.py
@@ -3311,23 +3311,28 @@ class SQLTABLE(TABLE):
if not sqlrows:
return
REGEX_TABLE_DOT_FIELD = sqlrows.db._adapter.REGEX_TABLE_DOT_FIELD
+ fieldmap = dict(zip(sqlrows.colnames, sqlrows.fields))
+ tablemap = dict(((f.tablename, f.table) for f in fieldmap.values()))
+ for table in tablemap.values():
+ pref = table._tablename + '.'
+ fieldmap.update(((pref+f.name, f) for f in table._virtual_fields))
+ fieldmap.update(((pref+f.name, f) for f in table._virtual_methods))
+ field_types = (Field, Field.Virtual, Field.Method)
if not columns:
columns = list(sqlrows.colnames)
- if headers == 'fieldname:capitalize':
+ header_func = {
+ 'fieldname:capitalize': lambda f: f.name.replace('_', ' ').title(),
+ 'labels': lambda f: f.label
+ }
+ if isinstance(headers, str) and headers in header_func:
+ make_name = header_func[headers]
headers = {}
for c in columns:
- tfmatch = REGEX_TABLE_DOT_FIELD.match(c)
- if tfmatch:
- (t, f) = REGEX_TABLE_DOT_FIELD.match(c).groups()
- headers[t + '.' + f] = f.replace('_', ' ').title()
+ f = fieldmap.get(c)
+ if isinstance(f, field_types):
+ headers[c] = make_name(f)
else:
headers[c] = REGEX_ALIAS_MATCH.sub(r'\2', c)
- elif headers == 'labels':
- headers = {}
- for c in columns:
- (t, f) = c.split('.')
- field = sqlrows.db[t][f]
- headers[c] = field.label
if colgroup:
cols = [COL(_id=c.replace('.', '-'), data={'column': i + 1})
for i, c in enumerate(columns)]
@@ -3380,9 +3385,8 @@ class SQLTABLE(TABLE):
_class += ' rowselected'
for colname in columns:
- matched_column_field = \
- sqlrows.db._adapter.REGEX_TABLE_DOT_FIELD.match(colname)
- if not matched_column_field:
+ field = fieldmap.get(colname)
+ if not isinstance(field, field_types):
if "_extra" in record and colname in record._extra:
r = record._extra[colname]
row.append(TD(r))
@@ -3390,12 +3394,9 @@ class SQLTABLE(TABLE):
else:
raise KeyError(
"Column %s not found (SQLTABLE)" % colname)
- (tablename, fieldname) = matched_column_field.groups()
- colname = tablename + '.' + fieldname
- try:
- field = sqlrows.db[tablename][fieldname]
- except (KeyError, AttributeError):
- field = None
+ # Virtual fields don't have parent table name...
+ tablename = colname.split('.', 1)[0]
+ fieldname = field.name
if tablename in record \
and isinstance(record, Row) \
and isinstance(record[tablename], Row):