it turned out that I could not do it as shown above because of
form.accepts. This already performs the upload so now I'm doing it
more like you suggested which is even more straightforward.

form = SQLFORM.factory(
    Field('invoice_logo', 'upload', label=T('as.invoice_logo'),
uploadfolder=os.path.join(request.folder,'uploads/')),
    Field('invoice_logo_filename',
label=T('as.invoice_logo_filename')),
    ... many other fields ...
    table_name='admin_setting')

if form.accepts(request.vars, formname='admin_setting_form',
dbio=False):
    if request.vars.invoice_logo != None:
        if type(request.vars.invoice_logo) != str:
            request.vars.invoice_logo_filename =
request.vars.invoice_logo.filename
            invoice_logo_newfilename =
form.vars['invoice_logo_newfilename']
        else:
            del request.vars.invoice_logo # do not clear current logo
filename

        for setting in request.vars:
            if not setting.startswith('_'):
                old_file = None
                if setting == 'invoice_logo':
                    old_file = db(db.admin_setting.name ==
'invoice_logo').select(db.admin_setting.value).first().value
                    value = invoice_logo_newfilename
                else:
                    value = request.vars[setting]
                if old_file:
                    try:
                        os.remove(os.path.join(request.folder,
'uploads/', old_file))
                    except OSError:
                        pass
                db(db.admin_setting.name ==
setting).update(value=value)



one question about the download:
def download():
    import os
    filename = request.args(0)
    original_filename = request.vars.filename
    filename = os.path.join(request.folder, 'uploads/', filename)
    ret = open(filename, 'rb')
    response.headers['Content-Type'] = 'application/octet-stream'
    response.headers['Content-Disposition'] = 'inline; filename="%s"'
% original_filename
    return ret.read()

do I have to take care about directory traversals and other security
risks? What's the easiest way to do this?

On 7 Okt., 02:47, TheSweetlink <yanosh...@gmail.com> wrote:
> My pleasure Alex.  I am glad that worked out for you.  Now that I look
> at your code you got it to work in a way I didn't even think of.  May
> we see a more complete example of your SQLFORM.factory?
>
> Massimo,
> I don't think I would know how to make it better other than Alex's
> suggestion of adding some more info to the Book.
>
> Especially when Alex came up with another way to do the manual upload
> I think it's cool that web2py is that flexible.
>
> I know it must be difficult to keep it all up to date with all the new
> features cropping up left and right.  Nice work by the way to all that
> did the most recent updates.
>
> Viva web2py and its magnificent community,
> David
>
> On Oct 6, 4:12 pm, Alex <mrauc...@gmail.com> wrote:
>
>
>
> > Hi David,
>
> > works great, thanks!
>
> > I'm now manually uploading with these few lines:
> > field = Field('invoice_logo', 'upload',
> > uploadfolder=os.path.join(request.folder,'uploads/'))
> > field._tablename = 'admin_setting'
> > uploaded_invoice_logo_filename =
> > field.store(request.vars.invoice_logo.file,
> > request.vars.invoice_logo.filename)
>
> > @Massimo: now that I know, it's quite easy so I don't know much to
> > make it better. It would be good if this would be mentioned in the
> > documentation (there is already a short 'Manual Uploads' section),
> > although this is probably not a common use case. And maybe it would be
> > a good idea to have default values for uploadfolder and tablename?
>
> > On 6 Okt., 03:46, Massimo Di Pierro <massimo.dipie...@gmail.com>
> > wrote:
>
> > > Suggestions to make the behaviour better?
>
> > > On Oct 5, 5:55 pm, TheSweetlink <yanosh...@gmail.com> wrote:
>
> > > > Hello Alex,
>
> > > > Two things I've found when manually uploading via SQLFORM.factory:
>
> > > > 1)  You need to specify a table_name='...' to avoid the
> > > > no_table_newfilename.extension issue like this:
>
> > > > form = SQLFORM.factory(...Field definitions...,
> > > > table_name='some_table_name')
>
> > > > 2)  Additionally you must specify an uploadfolder in your upload Field
> > > > definition similar to this:
>
> > > > form = SQLFORM.factory(...,
> > > > Field('invoice_logo', type='upload',
> > > > uploadfolder=os.path.join(request.folder,'static/uploads/')),
> > > > ..., table_name='whatever_you_like')
>
> > > > **NOTE** 'static/uploads' is just an example, you can upload to
> > > > wherever it will be appropriate.
>
> > > > In this case the newly uploaded and renamed file to
> > > > your_application's_dir/static/uploads/your_new_filename_here
>
> > > > One gotcha to look out for following your field name as an example
> > > > without the quotation marks:
>
> > > > In your form.accepts(...):
>
> > > > "request.vars.invoice_logo" will contain the original filename of your
> > > > upload whereas
>
> > > > "form.vars.invoice_logo_newfilename" will contain the newly renamed
> > > > file like yourtablename.9203842903.thaoeu09gu023hgda3p.ext
>
> > > > No need to call store() directly as SQLFORM.factory will take care of
> > > > that for you.
>
> > > > I hope that this helps you.
>
> > > > -David Bloom
>
> > > > On Oct 4, 7:53 pm, Alex <mrauc...@gmail.com> wrote:
>
> > > > > Hi,
>
> > > > > I've already spent quite some time with the following problem which I
> > > > > think should be fairly easy. I hope someone can help me.
>
> > > > > # model
> > > > > db.define_table('admin_setting',
> > > > >     Field('name', 'string', notnull=True),
> > > > >     Field('value', 'string', notnull=True))
>
> > > > > in the controller I'm creating a form for various admin settings.
> > > > > form = SQLFORM.factory(
> > > > >         Field('invoice_logo', 'upload'), ...)
>
> > > > > the view works well and displays all fields.
>
> > > > > When uploading a file for the logo the file should be handled like
> > > > > always (file uploaded to uploads folder, renamed to uuid filename). in
> > > > > the table admin_setting I want to store the filename of the uploaded
> > > > > file in a row where name='invoice_logo' (the filename should be stored
> > > > > in the value field).
>
> > > > > How can I achieve this? currently I have this code (the update is
> > > > > performed later and not shown here):
> > > > > if form.accepts(request.vars, formname='admin_setting_form',
> > > > > dbio=False):
> > > > >   if request.vars.invoice_logo != None:
> > > > >     if type(request.vars.invoice_logo) != str:
> > > > >       request.vars.invoice_logo_filename =
> > > > > request.vars.invoice_logo.filename
> > > > >       field = Field('invoice_logo', 'upload')
> > > > >       # field.store fails because field does not have a _tablename
> > > > >       uploaded_file = field.store(request.vars.invoice_logo.file,
> > > > > request.vars.invoice_logo.filename)
> > > > >     else:
> > > > >        del request.vars.invoice_logo # do not delete existing logo

Reply via email to