flask request.files empty even though request.args is not - python

I'm trying to upload a file to a flask server from a form. My HTML (I'm using React) is as follows:
<form action="/" method="post">
<input type="file" id="placesCSV" name="placesCSV"></input>
<input type="submit" />
</form>
But the following code in python:
#app.route('/', methods = ['POST'])
def findRoutes():
if request.method == 'POST':
print(request.args)
print(request.files)
Prints the filename correctly for request.args, but request.files is empty. I'm also getting:
Bad Request
The browser (or proxy) sent a request that this server could not understand.
I've tried the same with 'GET' instead of 'POST' and I have the same result.

I think you should change the request.method to POST
def findRoutes():
if request.method == 'POST':
print(request.args)
print(request.files)

Related

form action in flask not redirecting to the route

Simply I am just trying to redirect to an url by using the below code in my login.html template:
<form>
<form action="/sessions">
<p>Username:</p>
<p><input type="text" minlength="8" name="username"required /></p>
<p>Password:</p>
<p><input type="text" name="password"/></p>
<input type="submit" value="Submit">
</form>
and
def login():
print("inside login")
return render_template('login.html')
#app.route("/sessions", methods=["GET","POST"])
def sessions():
userid = request.form.get("userid")
password = request.form.get("password")
return request.form.get("userid"), request.form.get("password")
but is stuck on the login() url. Also I tried
<form action="{{ url_for('sessions') }}">
but is not working as well. Not sure what I am missing? Please any hints/ideas would be highly appreciated.
Try this ( i just added one more line, the commented one):
#app.route("/sessions", methods=["GET","POST"])
def sessions():
userid = request.form.get("userid")
password = request.form.get("password")
if request.method == 'POST': #additional line
return request.form.get("userid"), request.form.get("password")
Updated answer reflects new comments
Found couple issues in your code:
HTML form is incorrect, you are using form in form
<form>
<form action="/sessions">
<p>Username:</p>
<p><input type="text" minlength="8" name="username"required /></p>
<p>Password:</p>
<p><input type="text" name="password"/></p>
<input type="submit" value="Submit">
</form>
You should change it to this
<html>
<body>
<h1>This is login page</h1>
<form action="{{ url_for('login') }}" method="POST">
<p>Username:</p>
<p><input type="text" minlength="8" name="username"required /></p>
<p>Password:</p>
<p><input type="text" name="password"/></p>
<input type="submit" value="Submit">
</form>
</body>
</html>
Notice changes, first there is only 1 form tag, then I use jinja2 engine to call the login in form.action, 2nd this login page handles serving login HTML when there is a GET request (initially opening this page) and for accepting form POST request with credentials.
Then I changed the routes to this:
from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)
#app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
user_name = request.form['username']
password = request.form['password']
print(user_name, password) # do something here?
return redirect(url_for('session'))
return render_template('login.html')
#app.route('/session')
def session():
return render_template('session.html')
Notice that now login accepts both methods, GET and POST, as mentioned before, GET is for serving HTML content and POST is for submitting form data. In the login endpoint I have a condition that checks, if it's a POST method request, then I extract credential details from request.form and after doing something (e.g. in that print() statementIreturn redirect(url_for('session'))`.
This is how you manage redirects from one page to another by clicking submit on one of a pages.
original answer that was incorrect
In Flask to redirect, you could you something like this:
from flask import url_for, redirect
#app.route('/sessions', methods['GET', 'POST']
def sessions():
# some code
return redirect(url_for('some.endpoint'))
This will redirect you to a specific endpoint that you will provide. In the docs there is more info about it.

Struggling to get data from POST request data from a HTML form with flask

I've been working on a website back-end using the python library flask but whenever I try and get the form data from a POST request (as it needs to be sent securely) I always get a 405 - Method not allowed error. After the submission of a user's email and password at the moment its just meant to send them to a very basic html page with their name and email on it (it's easier to explain with the code).
python code:
# reroutes user to login page html file
#app.route("/")
#app.route("/login", methods=["GET", "POST"])
def reroute_login():
return flask.render_template("login.html")
# returns the login page html file
#app.route("/login", methods=["GET", "POST"])
def login():
if flask.request.method == "POST":
print("Reached")
email = flask.request.form["email"]
password = flask.request.form["password"]
print(email, password)
return flask.redirect(flask.url_for("user", usr=email))
else:
return flask.render_template("login.html")
#app.route("/<usr>")
def user(usr):
return f"<h1>{usr}</h1>" # here is that very basic html page I mentioned but it won't reroute to this page
login.html:
<form action="#" method="post">
<h1>Login</h1>
<input type="text" name="email" placeholder="Email">
<input type="password" name="password" placeholder="Password">
Forgot Your Password
<input type="submit" class="button1" value="submit" />
</form>
Please just know I'm very new to Flask and back-end web dev as a whole but any kind of help would be much appreciated :)
Try changing action in login.html from # to /login .
And you have defined multiple routes with same name.
Remove the first route to login.

Why does html POST take me to an unexpected page?

I have a simple web application built with Python using flask that has three pages: main, index, and post. I am trying to get to the "if request.method == "POST"" section of the index page. To test this I've asked it to render the post.html page. For some reason when I send a POST method from the index page I'm instead being redirected to my main_page. The python code looks like this:
from flask import Flask, redirect, render_template, request, url_for
app = Flask(__name__)
app.config["DEBUG"] = True
#app.route("/", methods=["GET", "POST"])
def index():
if request.method == "GET":
return render_template("main_page.html")
#implied ELSE here (if it's not GET, do the following for a POST)
return redirect(url_for('index'))
#app.route('/index', methods=['GET', 'POST'])
def new_index():
if request.method == "POST":
#I AM TRYING TO GET HERE
return render_template('post.html')
if request.method == "GET":
return render_template('index.html',)
#app.route('/post')
def post():
return render_template('post.html')
The POST method from index.html comes from this:
<div class="row">
<form role="form" method='POST' action='.'>
<textarea class="form-control" name="contents" placeholder="Enter a comment"></textarea>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
I'm not particularly familiar with HTML but I've tried everything I can think of. Any advice?
When you want to link to the same page in a form action you should actually put a question mark, an empty string, a hash or just leave out the attribute all together. Doing either of these will fix your code.
<form role="form" method='POST' action='?'>
<form role="form" method='POST' action='#'>
<form role="form" method='POST' action=''>
<form role="form" method='POST'>
My personal preference is using.
<form role="form" method='POST' action='#'>
This will validate in XHTML and doesn't open up any known attack vectors.
First thing I did was testing your API using Postman, and that all works fine: GET goes to the GET handler, POST goes to the POST handler.
The error I found is in the html form, in particular the action tag: you should point that to the API handler explicitly, and relative to the hostname. So, for example, setting that to:
<form role="form" method='POST' action='/index'>
will actually perform a POST on the /index API of your Flask app.

400 Bad request from flask when using a page from a sub folder & submitting a form

Whenever I request the page, it loads fine, but when I submit the form, I receive a 400 bad request,I believe it may be to do with the actual html , but I cannot figure out what.
Html file /admin/dashboard.html :
<div class="container">
<p><strong>Shut down server?</strong></p>
<form action="/" method="POST">
<input class="btn btn-danger" id="fred" name="fred" type="submit" value="fred"></input>
</form>
</div>
Python file :
#app.route('/admin/dashboard', methods=['GET', 'POST'])
def admin_dashboard():
if request.method == 'GET':
return render_template("/admin/dashboard.html")
if request.method == 'POST':
if request.form['submit'] == 'fred':
admin.log("Shutting down...")
#os._exit(1)
else:
return render_template("/admin/dashboard.html")
return render_template("/admin/dashboard.html")
You are posting to the / path, but the view that handles your post is at /admin/dashboard. Remove the action="/" line from your form since it's the same url that rendered the page.
If you do need a different url, use url_for('name_of_endpoint'). For example, to generate the url for def admin_dashboard():, you use url_for('admin_dashboard').
Additionally, you named your input 'fred', so you need to access request.form['fred'], or change the name of the input to 'submit'.
You are checking if a field with name submit is present in the request:
if request.form['submit'] == 'fred':
But there is no such field, the field is actually named fred:
<input class="btn btn-danger" id="fred" name="fred" type="submit" value="fred"></input>
You should either change the request check:
if request.form['fred'] == 'fred':
Or change the inputs name:
<input class="btn btn-danger" id="fred" name="submit" type="submit" value="fred"></input>
In Flask doc
We recommend accessing URL parameters with get or by catching the
KeyError because users might change the URL and presenting them a 400
bad request page in that case is not user friendly.
so maybe you can try
request.form.get('submit', '')
so your code:
if request.method == 'POST':
if request.form.get('submit') == 'fred':
admin.log("Shutting down...")
#os._exit(1)
else:
return render_template("/admin/dashboard.html")
return render_template("/admin/dashboard.html")

Post values from an HTML form and access them in a Flask view

I have an HTML form that gets posted to a Flask route. However, request.form is empty. If I try to access one of the values by id, I get a 400 error. How do I post values from an HTML form and access them in Flask?
<form method="POST">
<input id="my_input" type="text" value="{{ email }}">
<input id="my_submit" type="submit" value="Submit">
</form>
#app.route('/page', methods=['POST', 'GET'])
def get_page():
if request.method == 'POST':
print(request.form) # prints ImmutableMultiDict([])
print(request.form['my_input']) # raises 400 error
return render_template('page.html')
Your input doesn't have a name attribute. That is what the client will pass along to the server. Flask will raise a 400 error if you access a form key that wasn't submitted.
<input name="my_input" id="my_input" type="text" value="{{ email }}">
You need to Specify the form Action method in the Html page, and then mention the HTML Text box name inside the Tag.
<form method="POST" action="/PythonFunctionName">
<input id="my_input" type="text" name="HTMLControlName" value="{{ email }}">
<input id="my_submit" type="submit" value="Submit">
</form>
And inside the .py module access the element using the name specified in the HTML tag.
#app.route('/PythonFunctionName', methods=['POST', 'GET'])
def getPage():
if request.method == 'POST':
strTextBoxVal= request.form['HTMLControlName'])
Print(strTextBoxVal)
return render_template('page.html')

Categories