|
|
## is52027c lab 13
|
|
|
|
|
|
in this lab we're going to look at flask's request object, including
|
|
|
|
|
|
* GET requests that pass some user input (i.e. a key/value pair in the url)
|
|
|
* POST requests submitted via a form
|
|
|
* basic validation
|
|
|
* uploading a file
|
|
|
* using flask's implementation of WTForms
|
|
|
|
|
|
##
|
|
|
|
|
|
<h1>task 1: adapting headlines for user input via GET</h1>
|
|
|
|
|
|
_note: my version of this in the lab-13 repo is get\_headlines.py_
|
|
|
|
|
|
* in this exercise, you will adapt your headlines project from the last lab to respond to user choices made via a GET request.
|
|
|
* this means making use of flask's request object http://flask.pocoo.org/docs/0.12/quickstart/#the-request-object
|
|
|
* you will implement a simple form that allows the user to choose which rss headlines to display; bbc, aljazeera or ap (associated press)
|
|
|
|
|
|
### rss feeds
|
|
|
|
|
|
you can use these or find some of your own:
|
|
|
|
|
|
* bbc: http://feeds.bbci.co.uk/news/rss.xml
|
|
|
* aljazeera : https://www.aljazeera.com/xml/rss/all.xml
|
|
|
* ap: http://hosted2.ap.org/atom/APDEFAULT/cae69a7523db45408eeb2b3a98c0c9c5
|
|
|
|
|
|
### add a form
|
|
|
|
|
|
* add a super simple form to your template that uses a text field to pass a value for 'publication'
|
|
|
* you don't need to explicitly add method or action as they will defualt to 'GET' and 'POST' which is what we want
|
|
|
|
|
|
|
|
|
### adapt the headlines view
|
|
|
|
|
|
* get the value of 'publication' from request.args
|
|
|
* fetch the headlines from that rss feed and pass them to the template
|
|
|
* use a default value for the case where no choice is passed
|
|
|
|
|
|
note that
|
|
|
|
|
|
request.args['publication']
|
|
|
|
|
|
will throw a key error if no value was passed.
|
|
|
|
|
|
so it's better to use
|
|
|
|
|
|
request.args.get('publication')
|
|
|
|
|
|
you check it exists, then if it does assign that value to you 'publication' variable
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
|
<h1>task 2: mocking up a login form using POST</h1>
|
|
|
|
|
|
_note: my version of this in the lab-13 repo is mock\_login.py_
|
|
|
|
|
|
* in this task you are simply asked to mock up a login form in flask
|
|
|
* you need a form that submits username & password via a POST request
|
|
|
* you need to extract those values and check them against stored values (we will just use CONSTANTS in this case)
|
|
|
|
|
|
### adding messaging
|
|
|
|
|
|
* well designed user interactions display helpful messages when something hasn't gone right
|
|
|
* flask helps you do this via 'message flashing' http://flask.pocoo.org/docs/0.12/quickstart/#message-flashing
|
|
|
* there's an example of using this with a login process at http://flask.pocoo.org/docs/0.12/patterns/flashing/#message-flashing-pattern
|
|
|
* you use get\_flashed\_messages() in the template to extract these messages for display
|
|
|
* flash messages use flask's session features to pass the message between a request (e.g. login attempt) and the next request (e.g. redisplaying the form with a message)
|
|
|
* for reasons which will be explained later, this means you need to set the value of app.secret\_key (it can be anything!)
|
|
|
|
|
|
|
|
|
task: create helpful messages for cases where username / password are missing or wrong
|
|
|
|
|
|
##
|
|
|
|
|
|
<h1> task 3: uploading files </h1>
|
|
|
|
|
|
_note: my version of this in the lab-13 repo is file\_upload.py_
|
|
|
|
|
|
* the following script will upload image files to the directory 'static/uploads'.
|
|
|
* you need to create that directory before running the script
|
|
|
* create your own version of this script
|
|
|
* work your way through each line in the upload_image view, making sure you understand what is going on
|
|
|
|
|
|
you should look up the path & listdir functions from the python standard library to check what they do:
|
|
|
* https://docs.python.org/3.5/library/os.html
|
|
|
* https://docs.python.org/3.5/library/os.path.html
|
|
|
|
|
|
you should also look up what secure_filename does: see the quickstart pages http://flask.pocoo.org/docs/0.12/patterns/fileuploads/
|
|
|
|
|
|
from flask import Flask
|
|
|
from flask import render_template, session, request
|
|
|
from flask import redirect, url_for, flash
|
|
|
from flask import send_from_directory
|
|
|
import os
|
|
|
from werkzeug.utils import secure_filename
|
|
|
|
|
|
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
|
|
|
UPLOAD_FOLDER = 'static/uploads'
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
|
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
|
|
|
|
|
|
# defining allowed file types for file upload
|
|
|
def allowed_file(filename):
|
|
|
return '.' in filename and \
|
|
|
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
|
|
|
|
|
|
@app.route('/')
|
|
|
def index():
|
|
|
files = [os.path.join(UPLOAD_FOLDER,f) for f in os.listdir(UPLOAD_FOLDER)]
|
|
|
return render_template('upload_index.html', files=files)
|
|
|
|
|
|
|
|
|
@app.route('/upload', methods = ['GET','POST'])
|
|
|
def upload_image():
|
|
|
if request.method == 'POST':
|
|
|
if 'file' not in request.files:
|
|
|
flash('no file part')
|
|
|
return redirect(request.url)
|
|
|
file = request.files['file']
|
|
|
if file.filename=='':
|
|
|
flash('no selected file')
|
|
|
return redirect(request.url)
|
|
|
if not allowed_file(file.filename):
|
|
|
flash('file type not allowed')
|
|
|
return redirect(request.url)
|
|
|
if file and allowed_file(file.filename):
|
|
|
filename = secure_filename(file.filename)
|
|
|
file.save(os.path.join(UPLOAD_FOLDER,filename))
|
|
|
flash('File "{}" successfully uploaded'.format(filename))
|
|
|
return redirect(url_for('index'))
|
|
|
return render_template('file_upload.html')
|
|
|
|
|
|
|
|
|
@app.route('/download/<filename>')
|
|
|
def download_file(filename):
|
|
|
print filename
|
|
|
return send_from_directory(UPLOAD_FOLDER,
|
|
|
filename)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
app.run(debug=True,host='0.0.0.0',port=8000)
|
|
|
|
|
|
|
|
|
### task: rendering images
|
|
|
|
|
|
create a template to display your uploaded images
|
|
|
|
|
|
##
|
|
|
|
|
|
<h1>wtforms</h1>
|
|
|
|
|
|
the flask extension flask-wtf implements the widely used python package, wtforms.
|
|
|
this makes it easy to set up safe and user-friendly forms.
|
|
|
|
|
|
* https://wtforms.readthedocs.io/en/latest/
|
|
|
* https://wtforms.readthedocs.io/en/latest/
|
|
|
|
|
|
first you will need to install flask-wtf:
|
|
|
|
|
|
pip install --user Flask-WTF
|
|
|
|
|
|
* task: review the quickstart docs for flask-wtf and see of you can figure out how to create and validate a form this way.
|
|
|
* https://flask-wtf.readthedocs.io/en/stable/quickstart.html
|
|
|
* the thing to remember is that flask-wtf helps you to generate the form _and_ to validate it.
|
|
|
* you can find a nice simple example / explanation at http://exploreflask.com/en/latest/forms.html
|
|
|
* note that the second part ('rendering forms') is halfway down that page
|
|
|
* don't worry about the csrf stuff at the moment! we'll go over that in the lectures
|
|
|
|
|
|
##
|
|
|
|
|
|
<h1>extension task: apply wtforms to file uploads</h1>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
|
keep developing this work during the week... |