0% found this document useful (0 votes)
7 views

Slides16 Flask

Uploaded by

Arslan Coskun
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

Slides16 Flask

Uploaded by

Arslan Coskun
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 35

CS6

Practical
System
Skills
Fall 2019 edition
Leonhard Spiegelberg
[email protected]
16.99 Recap
Last lectures: Basic + more advanced python

- Basic:
Comments, Numbers, Strings, Lists, Tuples, Dictionaries,
Variables, Functions, Lambdas, Slicing, String formatting,
Control Flow(if/for/while), builtin functions
- Advanced:
Comprehensions(list/set/dict), Decorators, Generators, Higher
order functions(map/filter), Basic I/O, Modules

2 / 35
17 Flask
CS6 Practical System Skills
Fall 2019
Leonhard Spiegelberg [email protected]
17.01 What is Flask?
⇒ lightweight python framework to
quickly build web applications

—> there are many other popular


python frameworks like Django,
Bottle, Falcon, web2py, ...

⇒ many extensions available for Flask


for forms, databases, authentication...

⇒ pip3 install flask

⇒ all examples from today available @


github.com/browncs6/FlaskExamples
4 / 35
17.02 Flask resources

Book:

Flask Web Development by


Miguel Grinberg. ISBN:
9781491991732

Websites:

http://flask.palletsprojects.com/en/1.1.x/

http://exploreflask.com/en/latest/

https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
5 / 35
17.03 The big picture

"backend"
HTTP GET /

Status: 200 <!DOCTYPE html>...

HTTP POST /login

Status: 200 <!DOCTYPE html>... web application written


in Flask
curl / browser / ...

⇒ a user requests (one or more) resource(s) via (one or more) URIs

—> web application written in Flask responds with content


6 / 35
17.04 Why use Flask?
⇒ allows to create dynamic websites, i.e. return dynamic content
and process requests!

⇒ static vs. dynamic websites == fixed vs. dynamic content

—> a static website delivers always the same content to


any user

⇒ What are examples for static and dynamic websites?

7 / 35
17.04 Static vs. Dynamic websites

Static Dynamic

API Documentation search engine


Blog (without comments or Disqus) online tax program
News page Banner
... ...

⇒ most websites are actually dynamic web applications. To create static


websites, use a static website generator like Jekyll! 8 / 35
17.05 A hello world application in flask
hw.py start via
from flask import Flask
python3 hw.py
app = Flask(__name__)
or via
# define routes here
@app.route('/')
def index(): export FLASK_APP=hw.py
return '<h1>Hello world</h1>' && flask run

if __name__ == '__main__':
app.run()

9 / 35
17.05 A detailed look
hw.py

from flask import Flask

app = Flask(__name__) web app object

# define routes here


@app.route('/')
def index(): decorator based on web app
return '<h1>Hello world</h1>' object to define routes

if __name__ == '__main__':
add debug=True here to
app.run()
enable auto reload of code
changes while you edit files

10 / 35
17.06 Defining routes in Flask
⇒ Basic idea: Return content for a route (i.e. the path + query
segment of an URI, e.g. /blog/12/03/09 )

⇒ Flask can assign parts of the urls to python variables!

@app.route('/blog/<int:year>/<int:month>/<title>')
def blog(title, month, year):
return '...'
Syntax is <varname>

Note: the order doesn't matter in


the python function. Optionally, a
flask filter can be applied to make
sure the URI part is of certain
type 11 / 35
17.06 Defining routes in Flask

@app.route('/blog/<int:year>/<int:month>/<title>')
def blog(title, month, year):
return 'Blog entry from {}/{}'.format(month, year)

types for Flask routes

string accepts any text without a slash (default)

int accepts integers

float accepts numerical values containing


decimal points

path similar to a string but accepts slashes

12 / 35
17.07 Responses and error codes
⇒ each HTTP response comes with a status code. You can explicitly
define them in your Flask application:
@app.route('/404') no content will be displayed,
def make404(): because 404 error!
return 'This page yields a 404 error', 404

⇒ for complete list of HTTP status codes and their meaning confer
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status

⇒ per default Flask returns 200 (HTTP OK)

⇒ if you defined a route with variables/types whose constraints are


violated, Flask will responds with 404 13 / 35
17.07 HTTP error pages
⇒ in order to display a custom error page for a certain HTTP code,
you can define a route in Flask via app.errorhandler()

error code / HTTP code

@app.errorhandler(404) error message


def notfound(error):
return "<h1>HTTP NOT FOUND ERROR</h1><p>{}</p>".format(error)

⇒ instead of explicitly returning, you may also use Flask's builtin function
abort(code, description=) to leave a route with an error code
14 / 35
17.08 Request and Response objects
⇒ when defining a route via flask, within the function a request
object is available holding details of the HTTP request

⇒ to create a response, a response object needs to be returned.


Flask has several helper functions to create response objects,
when returning a string per default it is treated as HTML response.

⇒ There are multiple types of requests (e.g. GET/POST), via


methods=[...] keyword argument a route can be restricted to
work only for specific requests.

15 / 35
17.08 Request object
from flask import request

@app.route('/get',methods=['GET'])
def get_route():
response = '<p>{} request {} issued<p><p>' \
'Headers<br>{}</p>' \
'<p>Query args:<br>{}'.format(request.method,
request.full_path,
request.headers,
request.args)
return response, 200

⇒ test via curl http://localhost:5000/get?a=10&b=30


or by entering a URL to this route to the browser
16 / 35
17.08 Response object
@app.route('/post', methods=['POST'])
def post_route():

body = '<table>'
for k, v in request.form.items():
body = '<tr><td>{}</td><td>{}</td></tr>'.format(k, v)
body += '</table>'

response = make_response(body)
response.headers['X-Parachutes'] = 'parachutes are cool'
return response

⇒ a post request can be issued via curl, e.g.


curl -sD - --form 'name=tux' \
--form 'profession=penguin' http://localhost:5000/post
17 / 35
17.09 URIs and responses
⇒ Note that a URI can return any content, i.e. you can also
generate images on-the-fly, csv files, videos, …

⇒ specify MIME-type (MIME=) when creating response


List of MIME types: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types

Example:
Return a csv file via route /csv
syntax alternative to
@app.route('/csv') make_response
def csv():
return app.response_class(response='a,b,c\n1,2,3\n4,5,6',
mimetype='text/csv')
18 / 35
Templating + static files
17.10 Templates
⇒ so far: custom written responses

—> cumbersome, better to use templates and fill in stubs!

⇒ Flask comes with a powerful template engine.

—> specify template path via


Flask(__name__, template_folder=...)
—> default template folder is templates/
—> in addition to templates, Flask can serve static files.
(Option: static_folder, default folder: static/)

⇒ Core idea: When creating a response, load template and fill in


placeholders using data from backend!
20 / 35
17.10 Jinja2 templates
⇒ Flask uses Jinja2 as template engine
https://jinja.palletsprojects.com/en/2.10.x/

⇒ Jinja2 has two types of stubs:

- {{ … }} print result of expression to template


- {% … %} execute statements, e.g. loops/if/...

⇒ use in flask via


render_template('home.html', title='Hello world')

stored in templates/ folder pass variable named title to template


with content 'Hello world'
21 / 35
17.10 Jinja2 template language
⇒ {{ expression }} replaces {{ … }} with the value of the expression
expression can be something like 2 * var, data.name or a
function registered to Jinja2
⇒ {% for … %} … {% endfor %}
allows to create complex HTML structure quickly
⇒ {% if … %} … {% endif %}
allows to create HTML code depending on condition
⇒ documentation under https://jinja.palletsprojects.com/en/2.10.x/templates/
Example:
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul> 22 / 35
17.10 Jinja2 templates in Flask - example

{{ title }} to replace
with title variable
folder structure
with default
folders for
templates and
static content url_for function to
create url relative to
static folder

23 / 35
17.11 More on templates
⇒ Jinja2 provides many helpful mechanisms like filters, macros, …

⇒ Especially useful is template inheritance.


—> use {% extends layout.html %} and
{% block name %} … {% endblock %} for inheritance

layout.html

blog.html landing_page.html
24 / 35
17.12 Template inheritance example
layout.html
<!DOCTYPE html> child.html
<html lang="en" dir="ltr"> {% extends 'layout.html' %}
<head> {% block body %}
<meta charset="utf-8"> <h1>Child example</h1>
<title>Template inheritance Block of parent replaced
example</title> with this content here.
</head> {% endblock %}
<body>
{% block body %}
<h1>Parent</h1>
<!-- empty template !--> child.html inherits from
{% endblock %} layout.html . Jinja2 replaces the
body block of the parent with the
content of child's one.
<p>q.e.d.</p>
</body>
</html> 25 / 35
HTML forms
17.13 Making websites interactive via forms
⇒ User input can be captured using forms
—> good resource on this topic:
Jon Duckett's HTML/CSS book Chapters 7 and 14

⇒ To define a form create one or more input fields <input>


enclosed in <form>...</form>tags.

⇒ When the submit button of a form is clicked a GET or POST


request will be issued to the URI defined under action.

—> input fields with a name attribute will be encoded.


27 / 35
17.13 General structure of input elements
<input type="..." name="..." value="...">

type of the input field,


can be e.g. text, When a form is
submit, checkbox, … submitted, data is
A list is available under encoded as
https://www.w3schools.com/ht name=value pairs.
ml/html_form_input_types.asp

28 / 35
17.13 forms example
<form action="/dest" method="GET">
<label for="textbox">Text Box</label><br>
<input type="text" name="textbox"><br><br>
<label for="password">Password Input</label><br>
<input type="password" name="password"><br><br>
<label for="textbox">Text Area</label><br>
<textarea name="textarea"></textarea><br><br>
<label for="dropdown">Dropdown</label><br>
<select id="dropdown">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select><br><br>
<label for="checkbox">Checkbox</label><br>
<input type="checkbox" name="checkbox"><br><br>
<label for="radio">Radio Select</label><br>
<input type="radio" name="radio">
<input type="radio" name="radio">
<input type="radio" name="radio"><br><br>
<label for="file">File</label><br>
<input type="file" name="file"><br><br>
<input type="submit" value="Submit Button">
</form> 29 / 35
17.13 Data encoding
⇒ Depending on the method (POST or GET) specified, the data of the form is
encoded in one of the following ways:

- When GET is used, the data becomes part of the URI


/calc?first_operand=12&second_operand=3
- When POST is used, the data is encoded in the body of the request message

<form action="/calc" method="get">


<input type="text" name="first_operand" value="0">
<select name="operator">
<option value="+">+</option>
<option value="-">-</option> Example form
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="text" name="second_operand" value="0"><br><br>
<input type="submit" id="submit" value="calculate" />
</form> 30 / 35
17.14 Accessing form data in Flask
⇒ Flask allows to easily access form data when a URI is invoked.
—> you can also simulate forms via curl and --form/-F option!
@app.route('/calc', methods=['POST'])
def calc():
res = 'undefined'
op1 = int(request.form['first_operand'])
op2 = int(request.form['second_operand']) extract form elements
op = request.form['operator']
from form dictionary
if op == '+':
res = op1 + op2
elif op == '-':
res = op1 - op2
elif op == '*':
res = op1 * op2
elif op == '/':
res = op1 / op2
else:
abort(404)
return render_template(...) 31 / 35
More complex flask applications
17.07 Organizing the module
⇒ So far: single .py file which held all logic.

⇒ A more complicated project might need multiple files! How to


structure them?

structure module as
folder with
__init__.py file!

33 / 35
17.08 Next steps
⇒ There are many extensions available for flask, e.g.

- flask-login provides decorators to secure routes


- flask-mail sending emails
- flask-cache cache routes
- flask-pymongo connect to MongoDB database
- flask-mysql connect to MySQL database
- flask-wtf wtforms integration (validators & Co)
- …

⇒ When developing your final project, some of these might be helpful!

34 / 35
End of lecture.
Next class: Thu, 4pm-5:20pm @ CIT 477

You might also like