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