cis 192: lecture 10 web development with flask
TRANSCRIPT
![Page 1: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/1.jpg)
CIS 192: Lecture 10Web Development with Flask
Lili Dworkin
University of Pennsylvania
![Page 2: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/2.jpg)
Last Week’s Quiz
req = requests.get("http://httpbin.org/get")
1. type(req.text)
2. type(req.json)
3. type(req.json())
![Page 3: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/3.jpg)
Last Week’s Quiz
req = requests.get("http://httpbin.org/get")
1. type(req.text)
<type ’unicode’>
2. type(req.json)
<type ’instancemethod’>
3. type(req.json())
<type ’dict’>
![Page 4: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/4.jpg)
Last Week’s Quiz
>>> def hi():
... return 0
...
>>> hi
<function hi at 0x1003bbc08>
>>> hi()
0
>>> type(hi)
<type 'function'>>>> type(hi())
<type 'int'>
![Page 5: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/5.jpg)
Last Week’s Quiz
>>> class Foo():
... def bar(self):
... return 0
...
>>> f = Foo()
>>> f.bar
<bound method Foo.bar of <__main__.Foo instance at 0
x1003caef0>>
>>> f.bar()
0
>>> type(f.bar)
<type 'instancemethod'>>>> type(f.bar())
<type 'int'>
![Page 6: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/6.jpg)
Last Week’s Quiz
1. type(json.dumps(json.loads('{"key": "val"}')))2. type(json.loads(json.dumps(0)))
![Page 7: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/7.jpg)
Last Week’s Quiz
1. type(json.dumps(json.loads('{"key": "val"}')))<type ’str’>
2. type(json.loads(json.dumps(0)))
<type ’int’>
![Page 8: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/8.jpg)
Last Week’s Quiz
I JSON isn’t a “type”
I JSON is a “format” – so strings can be valid JSON or notI json.dumps
I Input: Python data structure consisting of dicts, lists, ints,strings, or bools
I Output: String
I json.loadsI Input: String in valid JSON formatI Output: Python data structure
![Page 9: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/9.jpg)
Last Week’s Quiz
>>> json.dumps([1, 2, 3])
'[1, 2, 3]'>>> json.dumps(0)
'0'>>> json.dumps('a')'"a"' # note the double quotes
>>> json.dumps(f)
TypeError: <__main__.Foo instance at 0x1003caef0> is
not JSON serializable
![Page 10: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/10.jpg)
Last Week’s Quiz
>>> json.loads('[1, 2, 3]')[1, 2, 3]
>>> json.loads('0')0
>>> json.loads('a')ValueError: No JSON object could be decoded
>>> json.loads("a")
ValueError: No JSON object could be decoded
>>> json.loads('"a"')u'a'
![Page 11: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/11.jpg)
Last Week’s Quiz
Return the content type of a response object called req.
![Page 12: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/12.jpg)
Last Week’s Quiz
Return the content type of a response object called req.req.headers[’content-type’]
![Page 13: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/13.jpg)
Last Week’s Quiz
What is the main difference between GET and POST requests?
![Page 14: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/14.jpg)
Last Week’s Quiz
What is the main difference between GET and POST requests?GET requests send parameters in the URL.POST requests send parameters in the body.
![Page 15: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/15.jpg)
Last Week’s Quiz
Why does it matter?
I The server can see the data regardless of whether it is in theURL or the body.
I And if someone intercepts your package, so can they.
I But GET requests remain in browser history and can becached and bookmarked, so you want to avoid that withsensitive data.
I If you send information in the headers of your GET request,that’s “safe” (as long as you are over SSL).
I Point of the story: use GET for retrieving, POST for sending.
![Page 16: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/16.jpg)
Last Week’s Quiz
l = [lambda x: x + i for i in range(5)]
1. type(l)
2. l[0](0)
![Page 17: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/17.jpg)
Last Week’s Quiz
l = [lambda x: x + i for i in range(5)]
1. type(l)
<type ’list’>
(My typo: I really wanted type(l[0]) – what is that?)
2. l[0](0)
4
I i is a name, and throughout the loop it is being pointed atsuccessively higher integers
I When we refer to i, we get what it currently points to
![Page 18: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/18.jpg)
Web Frameworks
I We’ve been talking about making HTTP requests
I What about serving them?
I Flask is a “microframework” – small and simple, and you cansee how and why everything is happening
I Django is the “big guy on the block” – more fully featured,but also more black magic / mysterious
![Page 19: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/19.jpg)
Hello World
from flask import Flask
app = Flask(__name__)
@app.route('/')def hello_world():
return "Hello World!"
if __name__ == '__main__':app.run()
prompt$ python flask.py
* Running on http://127.0.0.1:5000/
![Page 20: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/20.jpg)
Hello World
app = Flask(__name__)
I When we create an instance of the Flask class, the firstargument is the name of the application’s module or package
I When using a single module, use __name__ because this willwork regardless of whether __name__ equals ’__main__’ orthe actual import name
![Page 21: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/21.jpg)
Hello World
@app.route('/')def hello_world():
return "Hello World!"
I The app.route('/') decorator tells Flask to call thehello_world() function when the relative url ’/’ is accessed
I The hello_world() function returns the web page (in thiscase, a simple string) to be displayed
![Page 22: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/22.jpg)
Hello World
app.run()
I The app.run() function runs the application on a local server
I This will only be visible on your own computer! We will talkabout deployment later
![Page 23: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/23.jpg)
Debugging
I When testing, use app.run(debug=True)
I Now the server will reload itself on code changes
I Additionally, you will see error messages in the browser
I But never leave this on in production!
![Page 24: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/24.jpg)
More Routing
@app.route('/bad')def bad():
return 'hi' + 4
@app.route('/bye')def bye_world():
return "Bye World!"
![Page 25: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/25.jpg)
Variable Rules
I To add variable parts to a url, use <variable_name>
I The variables are passed as arguments to the function
@app.route('/user/<username>')def greet_user(username):
return "Hello %s!" % username
![Page 26: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/26.jpg)
Variable Rules
Multiple urls can route to the same function:
@app.route('/name/<first>')@app.route('/name/<first>/<last>')def greet_name(first, last=None):
name = first + ' ' + last if last else first
return "Hello %s!" % name
![Page 27: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/27.jpg)
Templating
What about some real HTML?Flask uses a templating system called Jinja.
<!doctype html>
<title>Hello from Flask</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello World!</h1>
{% endif %}
Need to put this in a templates folder.
![Page 28: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/28.jpg)
Templating
from flask import render_template
@app.route('/template/')@app.route('/template/<name>')def template(name=None):
return render_template('index.html', name=name)
![Page 29: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/29.jpg)
Templating
Even cooler ...
<!doctype html>
<title>Making a List</title>
<ul>
{% for item in l %}
<li>{{ item }}</li>
{% endfor %}
</ul>
@app.route('/templatelist')def template_list():
l = ['a', 1, True]
return render_template('list.html', l=l)
![Page 30: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/30.jpg)
GET Requests
I Recall: a url can be accessed with parameters, e.g.:/hello?key=value
I Retrieve these parameters from the request.args dictionary
from flask import request
@app.route('/args')def args():
html = ''for key, value in request.args.items():
html += '%s=%s' % (key, value)
html += '<br/>'return html
![Page 31: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/31.jpg)
GET Requests
Even better, using templates:
<!doctype html>
<title>Displaying Params</title>
<ul>
{% for key, value in params.items() %}
<li>{{ key }}={{ value }}</li>
{% endfor %}
</ul>
@app.route('/template_args')def template_args():
return render_template('params.html',params=request.args)
![Page 32: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/32.jpg)
POST Requests
I We can also make POST requests to a url
I Add keyword argument methods=['POST', 'GET'] to theapp.route() decorator
I Check if a request was a POST by looking atrequest.method
I The data from a POST request can be retrieved from therequest.form dictionary
![Page 33: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/33.jpg)
POST Requests
@app.route('/post', methods=['POST', 'GET'])def post():
if request.method == 'POST':return request.form.get('data', 'default')
else:
return 'That was a GET request.'
>>> url = 'http://127.0.0.1:5000/post'>>> req = requests.post(url, data={'data':'test'})>>> req.text
u'test'>>> req = requests.post(url)
>>> req.text
u'default'
![Page 34: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/34.jpg)
POST Requests
What if we try sending a list?
>>> url = 'http://127.0.0.1:5000/post'>>> req = requests.post(url,
data={'data': [1, 2, 3]})
>>> req.text
u'1'
![Page 35: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/35.jpg)
POST Requests
Instead, use JSON! Only ever send strings across the wires.
@app.route('/postlist', methods=['POST'])def post_list():
l = request.form.get('data')l = json.loads(l)
return ','.join(map(str, l))
>>> url = 'http://127.0.0.1:5000/postlist'>>> resp = requests.post(url,
data={'data': json.dumps([1,2,3])})
>>> resp.text
1,2,3
![Page 36: CIS 192: Lecture 10 Web Development with Flask](https://reader031.vdocuments.mx/reader031/viewer/2022011803/61d353cb480c144b20798b7c/html5/thumbnails/36.jpg)
Returning JSON
Instead of returning HTML, what if we want to return JSON?
from flask import jsonify
@app.route('/json')def return_json():
return jsonify({'some': 'data'})
>>> url = 'http://127.0.0.1:5000/json'>>> req = requests.get(url)
>>> req.json()
{u'some': u'data'}