I have used it several times, I thought of doing a reusable class for it, but did't have time to do it yet.
For a query with only one table involved this is one code example.
I use the same code, with a small modifications in the way field values are requested, for queries with joined tables. That's why there are some variables here that might not make sense when only one table is used (table_order, table_search, etc.)
@service.json
def logs_table():
query_filter = None
if request.vars.start is not None:
iDisplayStart = int(request.vars.start)
else:
iDisplayStart = 0
if request.vars.length is not None:
iDisplayLength = int(request.vars.length)
else:
iDisplayLength = 10
if request.vars.draw is not None:
sEcho = int(request.vars.draw)
else:
sEcho = 1
def field_names(index):
name = request.vars['columns[%s][data]' % index]
return ('', name)
def field_names_join(index):
name = request.vars['columns[%s][data]' % index]
table = name.split("_")[0]
field = "_".join(name.split('_')[1:])
return (table, field)
if 'order[0][column]' in request.vars:
order_column = request.vars['order[0][column]']
else:
order_column = '0'
_, field_order = field_names(order_column)
table_order = 'api_logs'
orderby = db[table_order][field_order]
if 'order[0][dir]' in request.vars:
if request.vars['order[0][dir]'] == 'desc':
orderby = ~orderby
filtered_vars = dict(filter(lambda (a, b): b != '' and '[search][value]' in a, request.vars.items())).keys()
for var_name in filtered_vars:
col = var_name.replace('columns[', '').replace('][search][value]', '')
_, field_search = field_names(col)
table_search = 'api_logs'
field_type = db[table_search][field_search].type
if field_type == 'datetime':
dates = request.vars[var_name].split(' - ')
if len(dates) > 1:
fmt = '%d/%m/%Y'
start_date = datetime.strptime(dates[0], fmt)
end_date = datetime.strptime(dates[1], fmt) + timedelta(days=1)
new_filter = (db[table_search][field_search] >= start_date) & (db[table_search][field_search] < end_date)
elif field_type == 'boolean':
new_filter = db[table_search][field_search] == ('tr' in request.vars[var_name].lower() or
'ye' in request.vars[var_name].lower())
elif field_type in ('string', 'text'):
string_filter = request.vars[var_name]
new_filter = db[table_search][field_search].ilike('%s%%' % string_filter)
else:
new_filter = None
if new_filter:
if query_filter:
query_filter = query_filter & new_filter
else:
query_filter = new_filter
if query_filter is None:
query = db(query_filter).select(db.api_logs.ALL,
limitby=(iDisplayStart, iDisplayStart + iDisplayLength),
orderby=orderby)
iTotalRecords = db(query_filter).count()
aaData = []
for row in query:
datarow = {}
for col in row:
if row[col] is not None:
if col == 'api_logs' or '_record' in col:
# internal dal col names
continue
elif col == 'added': # datetime column , to be formatted
datarow[col] = row[col].strftime('%Y-%m-%d %H:%M:%S')
else:
datarow[col] = row[col]
else:
datarow[col] = ''
aaData.append(datarow)
return dict(draw=sEcho, recordsTotal=iTotalRecords, recordsFiltered=iTotalRecords, data=aaData)
José L.