0

How do I get Flask to return the user to the same page, filled out the same way, after he/she submits the form on the page? 'render_template' only seems to work if I know all the variables ahead of time. My form is dynamic, and the variables change depending on selections the user has made. See the psuedo-code below for what I'm thinking of. I know render_template doesn't work like this, but is there a way to just say "use the same form values that came in when rendering the template?"

@app.route('./MyPage', methods=['GET', 'POST'])
def MyPage():

  if request.method == 'POST':
    # Do some stuff
    # return render_template('MyPage.html', context=request.form)
  else:
    # Do some other stuff
DCB2524
  • 31
  • 1
  • 8
  • Clarify: You're wanting to return them to the page and have the form filled out with what they just submitted? Why? – cmrussell May 28 '19 at 01:53
  • I'm trying to create a "save" file of what the user filled out in .csv format for them to download. I'm taking the form input and sending them a .csv file so that they can upload it later and resume where they left off. After I send them the .csv file, I'd like to route them back where they were rather than have them fill it all out again. Maybe there's an easier way to do this? I'm a noob. – DCB2524 May 28 '19 at 02:03

1 Answers1

1

The simplest way to do a download in the way you are asking it to use target="_blank" on your form:

<form action="/MyPage" method="POST" target="_blank">
  <ul>
  {% for input in form %}
    <li>{{ input.label }} {{ input }}</li>
  {% endfor %}
  </ul>
</form>

Then your POST-handling method doesn't need to do anything else but return the CSV:

@app.route('/MyPage', methods=['GET', 'POST'])
def MyPage():
  if request.method == 'POST':
    # Turn `request.form` into a CSV
    # see https://stackoverflow.com/q/26997679/135978 for an example
    headers = {'Content-Disposition': 'attachment; filename=saved-form.csv', 'Content-Type': 'text/csv'}
    return form_as_csv, headers
  else:
    # Do some other stuff

If you need multiple buttons on the form, then instead of setting target on the form, you can just set formtarget="_blank" on the button that triggers the CSV:

<form action="/MyPage" method="POST">
  <ul><!-- ... snip ... --></ul>
  <button name="submit_action" value="SAVE_AS_CSV" formtarget="_blank">Save as CSV</button>
  <button name="submit_action" value="RUN_CALCULATION">Run Calculation</button>
</form>

Then you just need to add a check for request.form['submit_action'] in your if request.method == 'POST' block and you're off to the races:

if request.method == 'POST':
    if request.form['submit_action'] == 'SAVE_AS_CSV':
        # Return the CSV response
    else:
        # Return the calculation response

See also: Writing a CSV from Flask framework

Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • I should have been more clear. I actually have multiple submit buttons in the form, one for saving, and one for running calculations, so setting the forms target to "_blank" would work for one button but not the other. A helpful reference for converting to .csv though. – DCB2524 May 28 '19 at 03:12
  • Updated to support multiple form buttons without making them all `target=_blank` in behavior @DCB2524. – Sean Vieira Jun 04 '19 at 17:04