File Upload Hangs with Flask - python

I am trying to upload a file but the browser spinner rolls forever, server logs don't show updates and the file doesn't get uploaded. It sure is a newbie error but I have no clue what that is:-
static/index.html :-
html
form action="http://127.0.0.1:5000/upload" method="post" enctype="multipart/form-data"
input type="file" name="db"/
input type="submit" value="upload"/
/form
html
app.py
from flask import Flask
from flask import request
from werkzeug import secure_filename
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
#app.route('/upload', methods=['GET', 'POST'])
def upload_file():
print 'upload_file'
if request.method == 'POST':
print 'post'
f = request.files['db']
f.save(secure_filename(f.filename))
if __name__ == '__main__':
app.run(debug=True)
Thanks
Env: Flask 0.9, Jinja2-2.6 and Werkzeug-0.8.3 with Python 2.7 on Win7 x64 with IE9 and Chrome

The docs say you should use enctype="multipart/form-data".
Also, I might try method="POST" (uppercase), if only because defensive coding is a good habit, the defensive maneuver here being not assuming that Flask is bug-free.

Related

I am learning Flask and I am facing this issue

I am learning Flask. I wrote the basic code and I want the submitted text to display in the same page. I already wrote the html and connected it. How can I do this?
from flask import Flask, redirect, url_for,render_template, request
app = Flask(name)
#app.route("/", methods=["POST", "GET"])
def home():
if request.method == "POST":
user = request.form["nm"]
return redirect(url_for("/", user))
else:
return render_template("login.html")
if name == ("main"):
app.run(debug=True)
I've noticed that you've taken the code from Python Basics. Indeed they do not show how to format the HTML template of the redirect.
Luckily, they offer a tutorial that shows you how to feed retrieved data to an HTML template using Jinja2. This tutorial can be found here. In essence, you can use {{ variable }} in your HTML template. In Flask, you will have to specify the variable as argument in the render_template function.
Minimal example:
# app.py
#app.route('/result',methods = ['POST', 'GET'])
def result():
if request.method == 'POST':
variable = request.form['variable']
return render_template("result.html", variable=variable)
<!-- result.html -->
<p> This is your variable: {{ variable }} </p>
I advice you to also check out both the Flask and Jinja2 documentation, as they offer plenty comprehensive examples of how to work with callbacks and HTML templating.

Flask - Why doesn't this let me import image files?

I am trying to make an application that allows users to upload images from their computer. This is as part of my CS50x final project, so I'm working in the CS50 IDE. Here is the code for my application:
application.py
import os
from flask import *
app = Flask(__name__)
UPLOAD_FOLDER = 'uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.route('/')
def myindex():
return render_template("file_upload_form.html")
#app.route('/upload', methods = ['POST'])
def upload():
if request.method == 'POST':
file = request.files['file']
file.save(os.path.join(app.config['UPLOAD_FOLDER'], "test.jpg"))
return redirect("/")
if __name__ == "__main__":
app.run(debug=True)
file_upload_form.html
<html>
<head>
<title>upload</title>
</head>
<body>
<form action = "/upload" method = "post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type = "submit" value="Upload">
</form>
</body>
</html>
For the vast majority of files, when I submit the form, I get a 500 Internal Server Error with no traceback or explanation. Curiously though, some files it seems to work with. I have found two images that work: both JPEGs and both relatively small. All other images I have tried have caused the error.
I cannot work out what is causing the Server Error, or why some images work and others don't. Can anyone see any reason why it wouldn't work for other images?
Thanks
I tested out your code and it worked fine on my side, but there is a couple of additions i would make, just to make it more robust.
You are calling all your uploads test.jpg and there is no mechanism in place to ensure that the file that gets uploaded is a jpg file. So technically, i could upload a pdf and it would be renamed in to a test.jpg.
A better method is to just give the file - the same name it had, including the extension. If you want to re-name the file, rather strip the extension first and add it to the new filename like so:
ext = file.filename.rsplit('.', 1)[1].lower()
newFilename = 'newname.{}'.format(ext)
Also there is no MAX_CONTENT_LENGTH - I would add that as well.
So i re-wrote your python code to look like this:
import os
from flask import *
from werkzeug.utils import secure_filename
app = Flask(__name__)
UPLOAD_FOLDER = './uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['ALLOWED_IMAGES'] = set(['png', 'jpg', 'jpeg'])
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
def allowed_image(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_IMAGES']
#app.route('/')
def myindex():
return render_template("index.html")
#app.route('/upload', methods = ['POST'])
def upload():
if request.method == 'POST':
file = request.files['file']
if file and allowed_image(file.filename):
file.save(os.path.join(app.config['UPLOAD_FOLDER'], secure_filename(file.filename)))
return redirect(request.url)
if __name__ == "__main__":
app.run(debug=True)
You are sending the post to: <form action = "/success"...>
Where is your /success handler?
UPDATE:
Try:
if request.method == 'POST':
print(request.files)
print(request.form)
print(request.POST)
You need to check the logs to see what there error is.

Taking data from drop-down menu using flask

I'm completely new to flask, and really am completely lost with how to approach this. I've looked into other SO questions but I can't seem to get this working regardless.
I have a form as such:
<form class="teamSelection" method="POST" action="/submitted">
<select class="teamForm" id="teamDropdownSelector" type="text" name="teamDropdown" placeholder="Select A Team">
<option disabled selected>Select a game</option>
<option id="WatfordVSManchester Utd" value="">Watford VS Manchester Utd</option>
</select>
<input class="btn" type="submit" value="submit">
</form>
and my flask as so:
from flask import Flask
app = Flask(__name__)
#app.route("/submitted")
def hello():
return "hello world"
The goal is to take the content of the selected/submitted dropdown item, pass this to the flask file where I then use the team names to scrape information about the match. However at the moment I can't even seem to get the POST of the form to work and am at a complete loss. I appreciate this is a pretty vague and open-ended question, but I seriously don't know how else to figure this out.
Should I instead use jquery to detect when the dropdown has changed and use AJAX to send a POST to somehow call the script and pass the values into it?
Any help would be greatly appreciated.
EDIT
I thought I put this in the original post, but must have forgot.
I am currently running an apache localhost server, and am working with flask via pycharm. All I've done at the moment is install the flask package in pycharm, and haven't set any of it up like I've seen in some tutorials do when running from the command line. I assumed this step wasn't necessary, as I already have a server up and running with apache?
When it comes to backend stuff like this I really have no idea, so apologies if that's a stupid assumption.
I've changed the flask to:
from flask import Flask
app = Flask(__name__)
#app.route("/submitted", methods=['POST'])
def hello():
with open("newTest.csv", mode="w+") as file:
fileWriter = csv.writer(file)
fileWriter.writerow(['Time', 'HomeTeam', 'AwayTeam'])
file.close()
The reason being as I can see if this script is actually being called, if it is it will make a new csv file called newTest. After running the webpage and submitting no new csv file appears, so this script isn't being run, meaning it's likely due to me not configuring flask correctly?/The assumption that apache was enough was incorrect?
You have just to tell the flask method to accept POST request and to read parameters from the request
Example:
from flask import Flask, request
app = Flask(__name__)
#app.route("/submitted", methods=['POST'])
def hello():
myvariable = request.form.get("teamDropdown")
... your code ...
return "hello world"
So, your question is not about flask, but about fopen - you have to add a full file path including directory path script_dir = path.dirname(path.abspath(__file__)).
Flask script (modified for launching in my local copy of project):
from flask import Flask, render_template, request
import csv
from os import path
app = Flask(__name__)
script_dir = path.dirname(path.abspath(__file__))
#app.route ("/")
def index():
return render_template("index.html")
#app.route("/submitted", methods=["GET", "POST"])
def hello():
if request.method == "GET":
return render_template("index.html")
filefullpath = script_dir + '//newTest.csv'
with open(filefullpath, mode="w+") as file:
fileWriter = csv.writer(file)
fileWriter.writerow(['Time', 'HomeTeam', 'AwayTeam'])
file.close()
return "hello world"
index.html (in folder "/templates")
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
Test
<br>
<form class="teamSelection" method="POST" action="/submitted">
<select class="teamForm" id="teamDropdownSelector" type="text" name="teamDropdown" placeholder="Select A Team">
<option disabled selected>Select a game</option>
<option id="WatfordVSManchester Utd" value="">Watford VS Manchester Utd</option>
</select>
<input class="btn" type="submit" value="submit">
</form>
</body>
</html>
Modify your code as:
from flask import Flask
app = Flask(__name__)
#app.route("/submitted", methods=['POST'])
def hello():
return request.form['teamDropdown']
Please let me know if that helps.

Running a python script with HTML button

How can I call a python script when the button is html file is clicked?
I am trying to change the language of the website by clicking the button. This is what I have done so far, but I am getting an error when I hit the button "page not found" and "The current URL, foo, didn't match any of these." What am I doing wrong
login.html
<form action="/foo" method="post">
<input type="submit" name = "first_button" value="French">
<input type="submit" name = "second_button" value="Spanish">
</form>
views.py
from app import foo
def get_language_from_client(request):
new_lang= foo()
if new_lang=="fr":
client_lang="fr"
else:
client_lang = translation.get_language_from_request(request)
print "client_lang:", client_lang
if "en" in client_lang:
return 0
elif "nl" in client_lang:
return 1
elif "fr" in client_lang:
return 2
elif "pl" in client_lang:
return 3
elif "ru" in client_lang:
return 4
else:
print "Unknown language code:", client_lang
return 2
app.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('login.html')
#app.route('/foo')
def foo():
return "fr"
if __name__ == '__main__':
app.run()
My directory structure looks like
scriboxapp
-templates
-login.html
-views.py
-app.py
I would recommend using Flask for this.
Here's an example of what you can do:
index.html:
<form action="/foo" method="POST">
<input type="submit" value="French">
</form>
app.py:
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/foo', methods=['GET', 'POST'])
def foo():
'''execute whatever code you want when the button gets clicked here'''
return
if __name__ == '__main__':
app.run()
When you run your app.py file and navigate to the URL where the Flask webserver is running, which in this case is localhost, you will be presented with the index.html file.
In the above example, you can see that the button containing the value French will execute your /foo route. Your function with the proper route decorator /foo is where you can execute your desired code.
To get this working, your directory structure should look something like this:
- app
- templates
- index.html
- app.py

How to print output using only a POST Method?

How can I print something like this:
{
username = admin
email = admin#localhost
id=42
}
With only using a method = ['POST'] and without using render_template?
PS: I already made it run with ['GET']
Here's my code:
from flask import Flask, jsonify, request
app = Flask(__name__)
#app.route('/', methods=['POST'])
def index():
if request.method == 'POST':
return jsonify(username="admin",
email="admin#localhost",
id="42")
else:
if request.method == 'POST':
return jsonify(username="admin",
email="admin#localhost",
id="42")
if __name__ == "__main__":
app.run()
And what I get is a 405 Method error.
Hey make sure your trailing stashes in your html are correct.
you may refer to : Flask - POST Error 405 Method Not Allowed and flask documentation : http://flask.pocoo.org/docs/0.10/quickstart/
this
<form action="/" method="post">
and this is same same but different
<form action="" method="post">
Accessing it without a trailing slash will cause Flask to redirect to the canonical URL with the trailing slash.
Given your error 405, I am suspecting that this is your problem. GET is fine, because you will just be redirected.
Try returning the form (as biobirdman said) on a GET request. Not sure why you need the request.method == 'POST' conditional statement. The parameter methods=['POST'] in the route should suffice.
Try this:
from flask import Flask, jsonify, request
app = Flask(__name__)
#app.route('/', methods=['POST'])
def index():
return jsonify(username="admin", email="admin#localhost", id="42")
#app.route('/', methods=['GET'])
def form():
return "<form action='/' method='POST'>" \
"<input type='submit'>" \
"</form>"
if __name__ == "__main__":
app.run()

Categories