Introduction to Flask python framework
Tue August 11 2015
Flask
Flask
micro web development framework for python
microframework?
Yes, microframework
is NOT a full stack framework like Django
it covers basic web development stuff
Web server and debugger
Testing
Routing
Templating (jinja2)
Request data access
is based on two external libraries:
Jinja2: python template library
Werkzeug: HTTP utility library for Python.
Getting started
Getting started
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
Getting started
$ pip install Flask
$ python hello.py
* Running on http://localhost:5000/
Debugger
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
app.run(debug=True)
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(debug=True)
Testing
Testing Skeleton
import os
import flaskr
import unittest
import tempfile
class FlaskrTestCase(unittest.TestCase):
def setUp(self):
self.db_fd, flaskr.app.config['DATABASE'] = tempfile.mkstemp()
flaskr.app.config['TESTING'] = True
self.app = flaskr.app.test_client()
flaskr.init_db()
def tearDown(self):
os.close(self.db_fd)
os.unlink(flaskr.app.config['DATABASE'])
if __name__ == '__main__':
unittest.main()
Testing Skeleton
import os
import flaskr
import unittest
import tempfile
class FlaskrTestCase(unittest.TestCase):
def setUp(self):
self.db_fd, flaskr.app.config['DATABASE'] = tempfile.mkstemp()
flaskr.app.config['TESTING'] = True
self.app = flaskr.app.test_client()
flaskr.init_db()
def tearDown(self):
os.close(self.db_fd)
os.unlink(flaskr.app.config['DATABASE'])
if __name__ == '__main__':
unittest.main()
$ python flaskr_tests.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
Testing a feature
import os
import flaskr
import unittest
import tempfile
class FlaskrTestCase(unittest.TestCase):
...
...
...
def login(self, username, password):
return self.app.post('/login', data=dict(
username=username,
password=password
), follow_redirects=True)
def logout(self):
return self.app.get('/logout', follow_redirects=True)
...
...
...
if __name__ == '__main__':
unittest.main()
Testing a feature
import os
import flaskr
import unittest
import tempfile
class FlaskrTestCase(unittest.TestCase):
...
...
...
def login(self, username, password):
return self.app.post('/login', data=dict(
username=username,
password=password
), follow_redirects=True)
def logout(self):
return self.app.get('/logout', follow_redirects=True)
def test_login_logout(self):
rv = self.login('admin', 'default')
assert 'You were logged in' in rv.data
rv = self.logout()
assert 'You were logged out' in rv.data
rv = self.login('adminx', 'default')
assert 'Invalid username' in rv.data
rv = self.login('admin', 'defaultx')
assert 'Invalid password' in rv.data
...
...
...
if __name__ == '__main__':
unittest.main()
Testing a feature
import os
import flaskr
import unittest
import tempfile
class FlaskrTestCase(unittest.TestCase):
...
...
...
def login(self, username, password):
return self.app.post('/login', data=dict(
username=username,
password=password
), follow_redirects=True)
def logout(self):
return self.app.get('/logout', follow_redirects=True)
def test_login_logout(self):
rv = self.login('admin', 'default')
assert 'You were logged in' in rv.data
rv = self.logout()
assert 'You were logged out' in rv.data
rv = self.login('adminx', 'default')
assert 'Invalid username' in rv.data
rv = self.login('admin', 'defaultx')
assert 'Invalid password' in rv.data
...
...
...
if __name__ == '__main__':
unittest.main()
Testing a feature
$ python flaskr_tests.py
...
------------------------------------
Ran 2 tests in 0.332s
OK
Routing
Routing
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello World'
Routing: Variable rules
@app.route('/user/<username>')
def show_user_profile(username):
# show the user profile for that user
return 'User %s' % username
@app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return 'Post %d' % post_id
Routing: Http methods
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
do_the_login()
else:
show_the_login_form()
Templating
Templating
<!doctype html>
<title>Hello from Flask</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello World!</h1>
{% endif %}
/application.py
/templates
/hello.html
Application folder
templates/hello.html
from flask import render_template
...
...
...
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)
...
...
...
application.py
Templating
<!doctype html>
<title>Hello from Flask</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello World!</h1>
{% endif %}
100% Jinja2
Request Data Access
@app.route('/login', methods=['POST', 'GET'])
def login():
error = None
if request.method == 'POST':
if valid_login(request.form['username'],
request.form['password']):
return log_the_user_in(request.form['username'])
else:
error = 'Invalid username/password'
# the code below is executed if the request method
# was GET or the credentials were invalid
return render_template('login.html', error=error)
Responses
from flask import abort, redirect, url_for
@app.route('/')
def index():
return redirect(url_for('login'))
@app.route('/login')
def login():
abort(401)
this_is_never_executed()
@app.errorhandler(404)
def not_found(error):
resp = make_response(render_template('error.html'), 404)
resp.headers['X-Something'] = 'A value'
return resp
A little bit more...
Cookie handling
Session handling
Logging
Simple Flask application
Browser:
js, html ,css
Python WebServer
using Flask
Request
Response
Browser:
js, html ,css
Python WebServer
using Flask
Request
Response
1. User puts http://0.0.0.0:80/ in the browser
2. Flask returns content in index.html
# This route will show a form to perform an AJAX request
# jQuery is loaded to execute the request and update the
# value of the operation
@app.route('/')
def index():
return render_template('index.html')
Browser:
js, html ,css
Python WebServer
using Flask
Request
Response
3. Content is received and shown
Browser:
js, html ,css
Python WebServer
using Flask
Request
Response
4. User fills form and clicks "calculate server"
Browser:
js, html ,css
Python WebServer
using Flask
Request
Response
5. Browser makes an ajax call to http://0.0.0.0:80/add/2/4
$(function() {
$('a#calculate').bind('click', function() {
var a = $('input[name="a"]').val();
var b = $('input[name="b"]').val();
$.getJSON('/add/' + a + '/' + b,
{},
function(data) {
$("#result").text(data.result);
});
return false;
});
});
Browser:
js, html ,css
Python WebServer
using Flask
Request
Response
6. Webserver performs the addition of the number and return the result
@app.route('/add/<int:a>/<int:b>')
def add_numbers(a,b):
#a = request.args.get('a', 0, type=int)
#b = request.args.get('b', 0, type=int)
return jsonify(result=a + b)
Browser:
js, html ,css
Python WebServer
using Flask
Request
Response
6. The browser receives the data and shows it in the screen
couldn't be simpler :)
Let's see the source code
Application folder
app.py
from flask import Flask, render_template, request, jsonify
# Initialize the Flask application
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/add/<int:a>/<int:b>')
def add_numbers(a,b):
#a = request.args.get('a', 0, type=int)
#b = request.args.get('b', 0, type=int)
return jsonify(result=a + b)
if __name__ == '__main__':
app.run(
host="0.0.0.0",
port=int("80"),
debug=True
)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"
rel="stylesheet">
<script type=text/javascript>
...
...
</script>
</head>
<body>
<div class="container">
<div class="header">
<h3 class="text-muted">How To Manage JSON Requests</h3>
</div>
<hr/>
<div>
<p>
<input type="text" size="5" name="a"> +
<input type="text" size="5" name="b"> =
<span id="result">?</span>
<p><a href="javascript:void();" id="calculate">calculate server side</a>
</form>
</div>
</div>
</body>
</html>
index.html
...
<script type=text/javascript>
$(function() {
$('a#calculate').bind('click', function() {
var a = $('input[name="a"]').val();
var b = $('input[name="b"]').val();
$.getJSON('/add/' + a + '/' + b,
{},
function(data) {
$("#result").text(data.result);
});
return false;
});
});
</script>
...
References
Social
Thanks!
Flask Intro
By Jhon Jairo Roa
Flask Intro
Very simple introduction to flask main features.
- 1,972