Why Does Flask Lose My Post Data When It Redirects?
I’m trying to decide which Python web programming framework to use in the Software Carpentry course. Simplicity is the main criterion: in fact, other than “still a live project”, it’s the only criterion. Flask is a strong contender despite the fact that its documentation is written for people who already understand web programming—I can fill that in. What I’m struggling with now, though, is that the same “hide the details” approach that makes it approachable is also making debugging difficult.
For example, here’s a simple application:
from flask import Flask, render_template, request DEBUGGING = True app = Flask(__name__) def load_data(): return [ [True, "luke", "2011-05-03", "luke", "Figure this out"], [True, "luke", "2011-05-03", "yele", "Figure this out"], [False, "luke", "2011-05-03", "gvwilson", "Figure this out"] ] @app.route('/show/', methods=['POST', 'GET']) def show(): data = load_data() try: items = request.form['item'] count = str(len(items)) except KeyError: count = "no items" return render_template('show.html', data=data, count=count) if __name__ == '__main__': app.run(debug=DEBUGGING)
which I put in
show.py. Here’s the corresponding template, which I put in
<html> <body> <p><strong>count: 8</strong></p> <form name="todo" action="/show" method="POST"> <table border="1"> <tr> <th colspan="6">Active</th> </tr> <tr> <th>Select</th> <th>Number</th> <th>Creator</th> <th>Created</th> <th>Owner</th> <th>Task</th> </tr> <tr> <th colspan="6">Completed</th> </tr> <p><input type="submit" value="make active" /></p> </form> </body> </html>
I run the application:
$ python show.py * Running on http://127.0.0.1:5000/ * Restarting with reloader...
and then point my browser at
http://127.0.0.1:5000/show/ (note the trailing slash). As expected, Firebug tells me there has been one GET request, with no parameters.
I then tick off the first of the checkboxes and click “Submit”. According to Firebug, this causes a POST with “item=0” as the submitted data (good), which immediately redirects (code 301) to a GET to the same URL, but without any of the posted data. Now, according to the section on “Unique URLs / Redirection Behaviour” in the Flask documentation, if the URL specified in
app.route has a trailing ‘/’, then accessing the URL without the trailing slash automatically redirects to the URL with the trailing slash. But I’m submitting a URL with a trailing slash, so there shouldn’t be a redirect, and even if there is, why is the posted data being thrown away?
I’m clearly doing something wrong, and if it wasn’t a warm Saturday afternoon, I’d probably have figured it out by now. (But please don’t let that stop you from sending me tips :-). What I’d really like to know, though, is how the hell to explain whatever is going on to someone who’s new to web programming. I’ve tried teaching raw CGI programming to grad students in science and engineering—it usually fails because there are too many low-level details to master. I’d hoped that high-level frameworks like Flask and web2py would make this stuff more accessible, but the law of leaky abstractions may put them out of practical reach as well: if things that look like they ought to work don’t, and there’s no easy way for someone who is just learning this stuff to debug it, we’re dead in the water.