librelist archives

« back to archive

Fill out form + upload files -> return modified files to user

Fill out form + upload files -> return modified files to user

From:
rory donovan
Date:
2015-07-06 @ 19:12
Hi,

I've been poking around flask for the past few days, but still can't quite
figure out if it's set up to do what I'm after.

I wrote a little python script/application that converts input files for
one type of cellular simulation to input files for another type of
simulation.  It takes as input a set of text files, as well as a (yaml)
config file, and uses those two inputs to output a new set of files.

What I'd like to do is set up a web interface for this process, and have
users fill out a form to populate the yaml file, and have one of the form
fields be able to accept a directory of text files.  Once these inputs are
acquired and written on the server (in a temp dir?), I'd run my python
script, and spit back the new set of files as a download for the user.

I don't want to make users sign in (this is for a niche academic audience,
so traffic will not be huge), so it's not clear to me if I need a database
running or not.  All the examples I looked at lean heavily on databases,
but it seems like creating a tmp folder for each upload and then deleting
them afterwards would work fine.

So, is this possible?  Or am I trying to use the wrong tool for the job?
Sorry for the very basic questions; I'm new to all this.

Thanks,
Rory

Re: [flask] Fill out form + upload files -> return modified files to user

From:
james hedley
Date:
2015-07-06 @ 20:21
Hi Rory

You won't need a database, unless there's something you need to remember in
between requests (If you did need a database, consider something hosted
like Mongo, Cloudant or Redis, you can use for free up to a limit).

Uploading a single file is easy enough:


@app.route('/', methods=['GET', 'POST'])
def upload_file():
    html= '''
    <!doctype html>
    <html>
    <title>Hello</title>
    <a href=""><h1>Hello.</h1></a>
    <form action="" method=post enctype=multipart/form-data>
      <p><input type=file name=file>
         <input type=submit value=Upload>
    </form>
    '''
    if request.method == 'POST':
        file = request.files['file']
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
        #do some processing
    elif request.method == 'GET':
       html += "<a href="processed_files.tgz">download</a>"
    html += "</html>"
    response = make_response(html)
    return response

...or something like that.

Mutliple files might need some fancy javascript widget or other.

HTH

James


On 6 July 2015 at 20:12, rory donovan <donovanr@alumni.reed.edu> wrote:

> Hi,
>
> I've been poking around flask for the past few days, but still can't quite
> figure out if it's set up to do what I'm after.
>
> I wrote a little python script/application that converts input files for
> one type of cellular simulation to input files for another type of
> simulation.  It takes as input a set of text files, as well as a (yaml)
> config file, and uses those two inputs to output a new set of files.
>
> What I'd like to do is set up a web interface for this process, and have
> users fill out a form to populate the yaml file, and have one of the form
> fields be able to accept a directory of text files.  Once these inputs are
> acquired and written on the server (in a temp dir?), I'd run my python
> script, and spit back the new set of files as a download for the user.
>
> I don't want to make users sign in (this is for a niche academic audience,
> so traffic w ill not be huge), so it's not clear to me if I need a database
> running or not.  All the examples I looked at lean heavily on databases,
> but it seems like creating a tmp folder for each upload and then deleting
> them afterwards would work fine.
>
> So, is this possible?  Or am I trying to use the wrong tool for the job?
> Sorry for the very basic questions; I'm new to all this.
>
> Thanks,
> Rory
>

Re: [flask] Fill out form + upload files -> return modified files to user

From:
rory donovan
Date:
2015-07-08 @ 15:58
Thanks for the advice.  I got my app mostly working, and I'm just stuck on
how to offer the processed file for download.

James, I think I see how your suggestion defines the html within the
function, and then modifies it.  Is it possible to do something similar if
I'm using a static template/index.html set-up?

I'm also not sure if I understand the

if request.method == 'POST':
    ... do stuff ...
elif request.method == 'GET':
    ... offer download ...

structure. I've included the code for my form page below, do you think it
would work with that?

Code:

@app.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():

        # set config dict with form info
        cfg = {}
        cfg['env'] = {}
        cfg['model'] = {}
        cfg['WE'] = {}
        cfg['WE']['bins'] = {}
        cfg['data'] = {}

        cfg['env']['python'] = str(form.python_home.data)
        cfg['env']['westpa'] = str(form.westpa_home.data)
        cfg['model']['observable_1'] = str(form.pcoord.data)
        cfg['model']['model_name'] = str(form.model_name.data)
        cfg['WE']['iters'] = int(float(form.iters.data))
        cfg['WE']['stride'] = int(float(form.stride.data))
        cfg['WE']['bins']['int'] = True
        cfg['WE']['bins']['target_count'] = int(float(form.targ_count.data))
        cfg['WE']['bins']['min_pcoord'] = int(float(form.min_pcoord.data))
        cfg['WE']['bins']['max_pcoord'] = int(float(form.max_pcoord.data))
        cfg['WE']['bins']['bin_size'] = int(float(form.bin_size.data))
        cfg['data']['log_all_species'] = True
        cfg['data']['rec_freq'] = int(float(form.rec_freq.data))

        # write yaml file of configs for weightedensemblizer script to use
        yaml_path = os.path.join(app.config['UPLOAD_FOLDER'],
'configs.yaml')
        with open(yaml_path, 'w') as outfile:
            outfile.write( yaml.dump(cfg, default_flow_style=False) )

        # save the uploaded file
        file = form.zipfile.data
        if file and allowed_file(file.filename):
            filename = secure_filename(form.zipfile.data.filename)
            file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            form.zipfile.data.save(file_path)

            # extract zipped model
            with zipfile.ZipFile(file_path) as zf:
                zf.extractall(app.config['UPLOAD_FOLDER'])

            # get safe absolute name of extracted folder -- only works if
zipped archive has model_name.zip as its name
            modeldirectory = os.path.abspath(os.path.splitext(file_path)[0])
            modelname_inferred = os.path.basename(modeldirectory)
            ouputdirectory = os.path.join(os.path.dirname(modeldirectory),
'we_'+str(modelname_inferred))

            # call main weighted ensemblizer function

weconvert.main(os.path.abspath(yaml_path),modeldirectory,ouputdirectory)

            # zip up the we output dir
            shutil.make_archive(ouputdirectory, 'zip', ouputdirectory)

        # end main action clause
        else:
            flash('Only upload .zip files, try again!')

        # end validate on submit clause
        return redirect(url_for('index'))

    # end index def
    return render_template('index.html',form=form)


On Mon, Jul 6, 2015 at 4:21 PM, james hedley <jameskhedley@gmail.com> wrote:

> Hi Rory
>
> You won't need a database, unless there's something you need to remember
> in between requests (If you did need a database, consider something hosted
> like Mongo, Cloudant or Redis, you can use for free up to a limit).
>
> Uploading a single file is easy enough:
>
>
> @app.route('/', methods=['GET', 'POST'])
> def upload_file():
>     html= '''
>     <!doctype html>
>     <html>
>     <title>Hello</title>
>     <a href=""><h1>Hello.</h1></a>
>     <form action="" method=post enctype=multipart/form-data>
>       <p><input type=file name=file>
>          <input type=submit value=Upload>
>  !   </ form>
>     '''
>     if request.method == 'POST':
>         file = request.files['file']
>         if file and allowed_file(file.filename):
>             filename = secure_filename(file.filename)
>         #do some processing
>     elif request.method == 'GET':
>        html += "<a href="processed_files.tgz">download</a>"
>     html += "</html>"
>     response = make_response(html)
>     return response
>
> ...or something like that.
>
> Mutliple files might need some fancy javascript widget or other.
>
> HTH
>
> James
>
>
> !
> On 6 July 2015 at 20:12, rory donovan <donovanr@alumni.reed.edu> wrote:
>
>> Hi,
>>
>> I've been poking around flask for the past few days, but still can't
>> quite figure out if it's set up to do what I'm after.
>>
>> I wrote a little python script/application that converts input files for
>> one type of cellular simulation to input files for another type of
>> simulation.  It takes as input a set of text files, as well as a (yaml)
>> config file, and uses those two inputs to output a new set of files.
>>
>> What I'd like to do is set up a web interface for this process, and have
>> users fill out a form to populate the yaml file, and have one of the form
>> fields be able to accept a directory of text! files.  Once these inputs are
>> acquired and written on the server (in a temp dir?), I'd run my python
>> script, and spit back the new set of files as a download for the user.
>>
>> I don't want to make users sign in (this is for a niche academic
>> audience, so traffic w ill not be huge), so it's not clear to me if I need
>> a database running or not.  All the examples I looked at lean heavily on
>> databases, but it seems like creating a tmp folder for each upload and then
>> deleting them afterwards would work fine.
>>
>> So, is this possible?  Or am I trying to use the wrong tool for the job?
>> Sorry for the very basic questions; I'm new to all this.
>>
>> Thanks,
>> Rory
>>
>
>

Re: [flask] Fill out form + upload files -> return modified files to user

From:
Corey Boyle
Date:
2015-07-06 @ 19:32
This link can help you with uploading files and collecting data via forms.

https://flask-wtf.readthedocs.org/en/latest/form.html#module-flask_wtf.file

What you are suggesting seems perfectly feasible to me, but I am a beginner to.
I've found http://amzn.com/1449372627 to be really helpful.

On Mon, Jul 6, 2015 at 3:12 PM, rory donovan <donovanr@alumni.reed.edu> wrote:
> Hi,
>
> I've been poking around flask for the past few days, but still can't quite
> figure out if it's set up to do what I'm after.
>
> I wrote a little python script/application that converts input files for one
> type of cellular simulation to input files for another type of simulation.
> It takes as input a set of text files, as well as a (yaml) config file, and
> uses those two inputs to output a new set of files.
>
> What I'd like to do is set up a web interface for this process, and have
> users fill out a form to populate the yaml file, and have one of the form
> fields be able to accept a directory of text files.  Once these inputs are
> acquired and written on the server (in a temp dir?), I'd run my python
> script, and spit back the new set of files as a download for the user.
>
> I don't want to make users sign in (this is for a niche academic audience,
> so traffic w ill not be huge), so it's not clear to me if I need a database
> running or not.  All the examples I looked at lean heavily on databases, but
> it seems like creating a tmp folder for each upload and then deleting them
> afterwards would work fine.
>
> So, is this possible?  Or am I trying to use the wrong tool for the job?
> Sorry for the very basic questions; I'm new to all this.
>
> Thanks,
> Rory