I encountered a little issue with SmartGrid not displaying custom links in Detail view. Not sure if I'm missing something or it's a limitation of some sort. Here's what's going on.
I have a main grid that looks like this:
There are different custom 'ACTIONS' buttons depending on 'APPROVAL' status. They all look and work fine in the grid itself. However, when I click on 'View' to display details, there's a "gluon.html" message instead of buttons, like so:
If there are no custom buttons on that row, I still get '[]' displayed instead of nothing:

Here's my code for the grid:
request_links = [dict(header='ACTIONS', body=lambda row: _create_requests_links(
row.id))]
grid = SQLFORM.smartgrid(db.otrequest, linked_tables = ['click_history','otrequest_archive'],
fields=[db.otrequest.description, db.otrequest.created_on, db.otrequest.ot_hours, db.otrequest.persons, db.otrequest.created_by, db.otrequest.approval, db.otrequest.approved_by, db.otrequest.approved_on],
links=dict(otrequest=request_links),
searchable= dict(otrequest=True, click_history=False),
editable= dict(otrequest=is_admin or (is_owner and is_not_approved_or_denied), otrequest_archive=False, click_history=False),
deletable= dict(otrequest=is_admin or (is_owner and is_not_approved_or_denied), otrequest_archive=False, click_history=not is_employee and is_assigned),
create=dict(otrequest=is_admin or is_manager or is_supervisor, otrequest_archive=False, click_history=False),
links_in_grid=True, user_signature=True,
details=dict(otrequest=True, otrequest_archive=False, click_history=False),
showbuttontext=True, paginate=30,
exportclasses=dict(otrequest=dict(json=False, csv_with_hidden_cols=False, tsv_with_hidden_cols=False),otrequest_archive=dict(json=False, html=False, xml=False, csv_with_hidden_cols=False, tsv_with_hidden_cols=False)),
orderby=orderby, oncreate=_on_create, formname='request_grid')
And here's the code that creates the buttons:
def _create_requests_links(record_id):
now = datetime.datetime.today()
rec_buttons = []
request_status=db(
db.otrequest.id == record_id).select().first()
assigned_count = db((db.click_history.request_rec == record_id) & (db.click_history.disposition == 'Assigned')).count()
# logger.debug("Count of Assigned for Request {}: People -> {}".format(record_id, db(
db.otrequest.id == record_id).select().first().persons))
if request_status is None:
return rec_buttons
elif request_status.approval == 0 and (auth.has_membership('manager') or auth.has_membership('admin')) and request_status.created_on > now:
rec_buttons.append(A(TAG.BUTTON(SPAN(_class="fa-regular fa-thumbs-up fa-lg"),T(' APPROVE')),callback=URL('default','_approve_this_request', args=[record_id]),_title="Approve This Overtime Request") + ' ')
rec_buttons.append(A(TAG.BUTTON(SPAN(_class="fa-solid fa-thumbs-down fa-lg"),T(' DENY')),callback=URL('default', '_deny_this_request', args=[record_id]),_title="Deny This Overtime Request"))
elif request_status.approval == 1 and assigned_count < db(
db.otrequest.id == record_id).select().first().persons and (auth.has_membership('supervisor') or auth.has_membership('admin')) and request_status.created_on > now:
rec_buttons.append(TAG.BUTTON(SPAN(_class="fa-solid fa-person-circle-plus fa-lg"),T(' ASSIGN'),_onClick="window.location='%s'" % URL('default','ot_rankings',args=[record_id]),_title="Assign Overtime to Employee"))
return rec_buttons