1

I am creating an app that does some analysis, given a user enters in some IDs into the form. For example, if a user types 12345, 23456 into the TextField form, the app will run some analysis on these IDs and then display the results. My problem is that currently, when the user clicks "Submit" and the data analysis completes, it always redirects the user to www.website.com/results. I need to create unique url's like www.website.com/results/12345+23456 so that 1) I can have multiple users and 2) users can send this link to people to re-generate the analysis.

Now, there are some questions on StackOverflow that are similar to my question but they are not the same and did not help me. So first, let me show some code before discussing that.

I have a home page which contains the the form:

    <div>
 <form action="https://website.com/results/" class="form-inline" method="post">
    <div class="form-group">
    <label for="PubmedID">Pubmed ID(s)</label>
    <input type="text" class="form-control" id="PubmedID" name="pmid" value="{{request.form.pmid}}">
  </div>
  <button type="submit" id= "myButton" class="btn btn-default" data-toggle="modal" data-target="#myModal">Submit</button>
</form>
</div> 

As you can see, the value for the form is request.form.pmid. My Flask-Wtform for this is here:

class pmidForm(Form):
    pmid = TextField('PubmedID')

Since the action of this form points towards website.com/results that triggers my Flask function to be called:

@app.route('/results/', methods=["POST"])
def results():
    form = pmidForm()
    try:
        if request.method == 'POST':

            #entry = request.form or request.data doesn't help me...
            entry = form.pmid.data #This is the user input from the form! 
            # DO LOTS OF STUFF WITH THE ENTRY 


    return render_template('results.html')

    except Exception as e:
        return(str(e))

As you can see I am using POST and form.pmid.data to get the data from the textfield form.

Again, I don't want to just redirect to /results, I'd like to expand on that. I tried to modify my form so that the form action pointed to https://website.com/results/{{request.form.pmid}}/ and then update the results function to be

@app.route('/results/<form_stuff>', methods=["POST"])
def results(form_stuff):

But this never worked and would re-direct me to a 404 not found page. Which I believe makes sense because there is no form data in the action when the HTML is first rendered anyway.

Now, the other post that mine is similar to is: Keeping forms data in url with flask, but it quite doesn't answer or solve my problem. For tthis post, the key point that people made was to use POST (which I already do), and to obtain and return the data with return request.args['query']. For me, I'm already processing the form data as I need to, and I have my return render_template() exactly how I want it. I just need to add something to the results URL so that it can be unique for whatever the user put into the form.

What do I need to add to my form in the html and to my Flask /results function in order to have the form data added into the URL? Please let me know if there's any other information I can provide to make my problem more clear. I appreciate the help! Thanks

SnarkShark
  • 360
  • 1
  • 7
  • 20
  • I would hash the combined ids and use that as the PK for the saved results. – Dan Aug 03 '17 at 18:00
  • @Dan can you expand on that? Hash the combined ids with what? A particular python library? Also what do you mean by "PK"? – SnarkShark Aug 03 '17 at 18:07
  • Save the results to DB and then redirect to /results/id where id is the PK of the results. You could also use query string params /results/?id=1&id=2 then you lookup the hash of the ids in the db. – Dan Aug 03 '17 at 18:23

1 Answers1

3

This isn't really a question about Flask.

If you want the data to show in the URL when you submit the form, you should use method="get" rather than "post". Then the URL will be in the form https://website.com/results/?pmid=12345.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • That seems like the exact opposite of what was discussed in https://stackoverflow.com/questions/20885937/keeping-forms-data-in-url-with-flask, which advises to use `post`. Can you explain how its different in my case? I think that I also need `post` in order to deal with the form data inside the results function. I will try `get` and see though, but flask-wtforms works with `post` as I have always used it. – SnarkShark Aug 03 '17 at 18:13
  • Update -- you are correct that "get" appended information to the URL, but this results in a 405 "The method is not allowed for the requested URL". Do I need to add something to the @app.route() then? – SnarkShark Aug 03 '17 at 18:18
  • Update -- I do not think "get" will work with wtforms. I changed everything to "get" and if I examine the form data it is "None" and class "NoneType". Perhaps then i would change to request.arg? – SnarkShark Aug 03 '17 at 18:37
  • Final update -- I changed the form method to "get" and also the method in /results to "get" and then accessed the data as `entry = (request.args.getlist('pmid'))[0]` – SnarkShark Aug 03 '17 at 18:52
  • This thread appears to be quite helpful for solving my own code issue. However, I'm stuck with what condition to use to process the form in the route. I've been using `if form.validate_on_submit():` to precede the relevant lines of code but this only works with the POST method. If I change to `if request.method == 'GET'` it makes my else statement redundant as this also uses the GET method. Is there another condition I can use that kicks in when the form is submitted using the GET method? – fdeboo Jul 05 '20 at 11:39