Hi Andy / Anthony,

May i ask how you have addressed the multi-tenant requirement separating 
all those uploaded files from different tenant to keep track of their 
storage usage.

I want to use the client id as part of the uploadfolder, it worked as a 
test below when I defined the uploadfolder in db.py with hardcoded 
client_id. In reality, the client_id varies (is there a way to specify the 
table company's id in the uploadfolder in db.py?), I thought of specifying 
the uploadfolder info in the action where I would do my upload 
(edit_company()), I could upload it but not download. 

Is it the same issue as Anthony mentioned (for test purpose, i used the 
same edit_company()'s SQLFORM to upload and download? i thought it would 
execute the line 
db.company.logo.uploadfolder=os.path.join(request.folder,'uploads', 
str(company_id)) before it executes  form=SQLFORM(db.company, 
record=record, deletable=True, showid=True, 
upload=URL('download')).process(), obviously i missed out some fundamental 
concept (no i didn't understand why Andy couldn't specify the table 
definition in the module as SQLFORM and view.html would be executed after 
calling attachment_module.define_tables()). Any insight will be much 
appreciated.

in db.py
client_id=3 #hard coded here for illustration
db.define_table('company',
Field('logo', 'upload', label='Company Logo', 
 uploadfolder=os.path.join(request.folder, 'uploads', client_id), 
uploadseparate=True, autodelete=True))

in default.py
def edit_company():
    company_id = request.args(0)
    record=db.company(company_id)
    db.company.logo.uploadfolder=os.path.join(request.folder,'uploads', 
str(company_id))
    db.company.chop.uploadfolder=os.path.join(request.folder,'uploads', 
str(company_id))
    form=SQLFORM(db.company, record=record, deletable=True, showid=True, 
upload=URL('download')
                 ).process()
    if form.accepted:
        session.flash='Info: you have updated your company details!!'
        redirect(URL('manage_company'))
    elif form.errors:
        response.flash='Error: inside edit_company, form raised error!!'
    else:
        pass
    return locals()

On Monday, May 9, 2016 at 10:29:00 PM UTC+8, Andy W wrote:
>
> I have a multi-tenant application, where users can upload files. I save 
> these in a different directory for each client (tenant), so I can keep tabs 
> on the overall disk space and number of files uploaded by each.
>
> This works fine when the table is defined in a model file - from the view 
> I can download existing files and upload new ones:
>
> Model:
> from gluon import *
> import os
> client_id=3 #hard coded here for illustration
>            
> db.define_table('attachment_model',
>     Field('attached_file', 'upload', label="Upload new file", 
>           uploadfolder=os.path.join(request.folder, 'uploads', str(
> client_id), 'attachments'),
>           requires=IS_NOT_EMPTY(), autodelete=True),
>     Field('filename', type='string', length=150, writable=False),
>     migrate=True)
>
> Controller:
> def model_based():
>     db.attachment_model.filename.readable=False
>     form_attachment=SQLFORM(db.attachment_model,
>                  autodelete=True, labels=None, deletable=True,
>                  fields=['attached_file'], submit_button='Attach file')
>     if hasattr(request.vars.attached_file, "filename"):
>         #save original file name
>         form_attachment.vars.filename=request.vars.attached_file.filename
>     if form_attachment.process().accepted:
>         response.flash = 'attachment saved'
>     elif form_attachment.errors:
>         response.flash = 'form has errors'
>     # list existing attachments
>     rows=db(db.attachment_model.id>0).select()
>     response.view = 'attachment.html'
>     return dict(form_attachment=form_attachment,
>                 rows=rows)
>
> View:
> {{extend 'layout.html'}}
> <h1>
>     Attached files
> </h1>
>     <table class="table-striped">
>         <thead>
>             <tr>
>                 <td>id</td>
>                 <td>filename</td>
>             </tr>
>         </thead>
>         <tbody>
>             {{for r in rows:}}
>                 <tr>
>                     <td>{{=r.id}}</td>
>                     <td>{{=A(r.filename, _href=URL('download', args=(str(
> client_id) + '/attachments/' + r['attached_file'])))}}</td>
>                 </tr>
>             {{pass}}
>         </tbody>
>     </table>
>     
> <h2>Add new attachment</h2>
> <div class="form-inline well">
>     {{=form_attachment}}
> </div>
>
> My issue is when I re-write the above so the model definition is moved to 
> a module.
>
> Module mod_attachment.py:
> from gluon import *
> import os
>
> class Attachment_module(object):
>     def __init__(self, db):
>         self.db = db
>
>     def define_tables(self):
>         db = self.db
>         client_id=3
>         if not 'attachment_module' in db.tables:
>             db.define_table('attachment_module',
>                 Field('attached_file', 'upload', label="Upload new file", 
>                       uploadfolder=os.path.join(current.request.folder, 
> 'uploads', str(client_id), 'attachments'), 
>                       requires=IS_NOT_EMPTY(), autodelete=True),
>                 Field('filename', type='string', length=150, writable=
> False),
>                 Field('request_tenant', type='integer', default=client_id,
>                       readable=False, writable=False),
>                 migrate=True)
>
> Revised controller:
> def module_based():
>     from mod_attachment import Attachment_module
>     attachment_module = Attachment_module(db) 
>     attachment_module.define_tables()
>     db.attachment_module.filename.readable=False
>     form_attachment=SQLFORM(db.attachment_module,
>                  autodelete=True, labels=None, deletable=True,
>                  fields=['attached_file'], submit_button='Attach file')
>     if hasattr(request.vars.attached_file, "filename"):
>         #save original file name
>         form_attachment.vars.filename=request.vars.attached_file.filename
>     if form_attachment.process().accepted:
>         response.flash = 'attachment saved'
>     elif form_attachment.errors:
>         response.flash = 'form has errors'
>     # list existing attachments
>     rows=db(db.attachment_module.id>0).select()
>     response.view = 'attachment.html'
>     return dict(form_attachment=form_attachment,
>                 rows=rows)
>
> With this approach, I can still list the uploaded files and add additional 
> ones (using the same view as before), but the download function no longer 
> works.
>
> So my question is why not? Do I have to modify the standard download 
> function, and how?
> Hope these are not daft questions - any pointers would be appreciated.
>
> Andy
>
>
>
>
>
>
>

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to