Achei um outro caminho melhor, usei o uploadfolder para criar pastas com o id dos registros.
Segue solução
Coloque no models a seguinte função
#####################################
def definir_uploadfolder(id_evento):
import os
caminho=os.path.join(request.folder,'uploads','eventos',str(id_evento))
# todos os campos que possuem upload relacionados com o evento
dbevento.arquivo_template.uploadfolder = caminho
dbevento.regras_submissao.uploadfolder = caminho
dbevento.logomarca_evento.uploadfolder = caminho
dbtrabalho.poster_digital.uploadfolder = caminho
dbtrabalho.oral_slide.uploadfolder = caminho
dbtrabalho.primeiro_envio.uploadfolder = caminho
dbtrabalho.trabalho_aceito.uploadfolder = caminho
dbversoes_trabalho.arquivo.uploadfolder = caminho
dbversoes_trabalho.arquivo_avaliador1.uploadfolder = caminho
dbversoes_trabalho.arquivo_avaliador2.uploadfolder = caminho
dbversoes_trabalho.arquivo_avaliador3.uploadfolder = caminho
dbanexo_inscricao.arquivo.uploadfolder = caminho
dbpagamento_inscricao.comprovante_anexado.uploadfolder = caminho
#como chamar
#definir_uploadfolder(linha_evento[0].id)
#na view
#<a href=
#"{{=URL(r=request,c='default',f='download_custom',
#args=[linha_evento[0].id,
# linha_versao_trabalho[0].arquivo]
#)}}">
#(Baixar esta versão do trabalho)
#</a>
#É necessário pernonalizar a função download do controller participante
# o return só é necessário se usar SQLFORM.factory por exemplo em participante.py função: cadastrar_anexo_inscricao
return caminho
####################################
No controller criei a função:
@cache.action()
def download_custom():
#Usado para identificar o id do evento, e sua pasta de download
id_evento=request.args(0)
definir_uploadfolder(id_evento)
return response.download(request, db)
####################################
Na telas de edição e inserção: chamei definir_uploadfolder(id_evento)
###################################
definir_uploadfolder(linha_evento[0].id)
if form.process().accepted:
session.flash = 'Evento editado com sucesso!'
redirect(URL(c='default',f='cadastrar_evento'))
else:
session.flash = 'você não tem permissão para editar esse registro'
redirect(URL(c='default',f='cadastrar_evento'))
#############################################
Para download direto na view:
<a href="{{=URL(r=request,c='default', f='download_custom',
args=[linha_evento[0].id,
linha_trabalho[0].oral_slide]
)}}"> (Baixar slide anexado) </a>
############################################
No caso de campos upload construidos com o SQLFORM.factory
campos=[dbanexo_inscricao.anexo,
Field('arquivo', 'upload', uploadseparate=True,
uploadfolder=definir_uploadfolder(linha_evento[0].id),
label= dbanexo_inscricao.arquivo.label,requires=dbanexo_inscricao.arquivo.requires),
]
form = SQLFORM.factory(*campos,
table_name='anexo_inscricao',
user_signature=False,args=request.args[:1])
########################################################
Desta forma dentro da pasta:
...\uploads\eventos\1\trabalho.oral_slide\9b\trabalho.oral_slide.9b0ca46b645bdc75.7461672068746d6c20696672616d652e747874.txt
A terceira pasta é o id do evento.