ď…“
Flask Basics
Eueung Mulyana
http://eueung.github.io/python/flask-basics
Python CodeLabs | Attribution-ShareAlike CC BY-SA
1 / 20
ď…“ Flask Basics
2 / 20
<ul>
{%forrowinrows%}
<li>{{row}}</li>
{%endfor%}
</ul>
templates/rows.jinja2.html
fromflaskimportFlask,render_template
app=Flask("app")
app.debug=True
deftop_articles():
return[
{"title":"Google","link":"http://google.com","date"
{"title":"Yahoo", "link":"http://yahoo.com","date"
]
@app.route('/')
defindex():
articles=top_articles()
returnrender_template("rows.jinja2.html",
rows=articles)
PORT=4001
app.run(host="0.0.0.0",port=PORT,use_reloader=False)
Example #1
 
3 / 20
Example #2
 
Notes:
If you enable debug support the server will reload itself
on code changes, and it will also provide you with a
helpful debugger if things go wrong
The route() decorator
Default Port 5000
fromflaskimportFlask
app=Flask(__name__)
#---------------------------------------------
@app.route('/')
defindex():
return'IndexPage'
@app.route('/hello')
defhello():
return'HelloWorld'
#---------------------------------------------
if__name__=='__main__':
#app.run()
app.run(host='0.0.0.0')
#app.debug=True
#app.run(debug=True)
hello.py
4 / 20
Example #3
Notes:
Variable rules
Unique URLs / redirection behaviours: trailing / vs. none
@app.route('/user/<username>')
defshow_user_profile(username):
#showtheuserprofileforthatuser
return'User%s'%username
@app.route('/post/<int:post_id>')
defshow_post(post_id):
#showthepostwiththegivenid,theidisaninteger
return'Post%d'%post_id
@app.route('/projects/')
defprojects():
return'Theprojectpage'
@app.route('/about')
defabout():
return'Theaboutpage'
Runningonhttp://0.0.0.0:5000/(PressCTRL+Ctoquit)
127.0.0.1--[22/Nov/201517:22:01]"GET/userHTTP/1.1"404
127.0.0.1--[22/Nov/201517:22:24]"GET/user/otongHTTP/1.1
127.0.0.1--[22/Nov/201517:26:11]"GET/postHTTP/1.1"404
127.0.0.1--[22/Nov/201517:26:23]"GET/post/2HTTP/1.1"
127.0.0.1--[22/Nov/201517:26:59]"GET/post/otongHTTP/1.1
127.0.0.1--[22/Nov/201517:27:52]"GET/projectsHTTP/1.1"
127.0.0.1--[22/Nov/201517:27:52]"GET/projects/HTTP/1.1"
127.0.0.1--[22/Nov/201517:28:30]"GET/projects/HTTP/1.1"
127.0.0.1--[22/Nov/201517:29:01]"GET/aboutHTTP/1.1"
127.0.0.1--[22/Nov/201517:29:05]"GET/about/HTTP/1.1"
5 / 20
Example #4
URL Building
...
Static Files
url_for('static',filename='style.css')
#static/style.css
fromflaskimportFlask,url_for
app=Flask(__name__)
@app.route('/')
defindex():pass
@app.route('/login')
deflogin():pass
@app.route('/user/<username>')
defprofile(username):pass
withapp.test_request_context():
printurl_for('index')
printurl_for('login')
printurl_for('login',next='/')
printurl_for('profile',username='JohnDoe')
$pythonapp.py
/
/login
/login?next=%2F
/user/John%20Doe
6 / 20
fromflaskimportFlask,request
app=Flask(__name__)
#---------------------------------------------
defdo_the_login():
return'DoLogin'
defshow_the_login_form():
return'ShowForm'
#---------------------------------------------
@app.route('/login',methods=['GET','POST'])
deflogin():
ifrequest.method=='POST':
returndo_the_login()
else:
returnshow_the_login_form()
#---------------------------------------------
if__name__=='__main__':
app.run(host='0.0.0.0',debug=True)
*Runningonhttp://0.0.0.0:5000/(PressCTRL+Ctoquit)
*Restartingwithstat
127.0.0.1--[22/Nov/201518:47:02]"GET/loginHTTP/1.1"
127.0.0.1--[22/Nov/201518:49:45]"POST/loginHTTP/1.1"
Example #5
HTTP Methods
 
7 / 20
Example #6
127.0.0.1--[23/Nov/201502:47:00]"GET/helloHTTP/1.1"
127.0.0.1--[23/Nov/201502:47:00]"GET/hello/HTTP/1.1"
127.0.0.1--[23/Nov/201502:49:03]"GET/hello/OtongHTTP/1.1"
fromflaskimportFlask,render_template
app=Flask(__name__)
#---------------------------------------------
@app.route('/hello/')
@app.route('/hello/<name>')
defhello(name=None):
returnrender_template('hello.html',name=name)
#---------------------------------------------
if__name__=='__main__':
app.run(host='0.0.0.0',debug=True)
<!doctypehtml>
<title>HellofromFlask</title>
{%ifname%}
<h1>Hello{{name}}!</h1>
{%else%}
<h1>HelloWorld!</h1>
{%endif%}
hello.html
8 / 20
fromflaskimportFlask,Markup
#---------------------------------------------
printMarkup('<strong>Hello%s!</strong>')%'<blink>hacker</blink>'
print"---"
printMarkup.escape('<blink>hacker</blink>')
print"---"
printMarkup('<em>Markedup</em>»HTML').striptags()
Example #7
Markup
9 / 20
References
Flask
Flask (A Python Microframework)
Flask Documentation
Flask @github
10 / 20
ď…“ Flaskr Microblog
11 / 20
Flaskr
Files & Folders
flaskr.py
initdb_flaskr.py
schema.sql
templates/layout.html
templates/login.html
templates/show_entries.html
static/style.css
schema.sql
droptableifexistsentries;
createtableentries(
idintegerprimarykeyautoincrement,
titletextnotnull,
'text'textnotnull
);
initdb_flaskr.py
sqlite3flaskr.db<schema.sql
importsqlite3
fromflaskimportFlask
fromcontextlibimportclosing
#---------------------------------------------
DATABASE='flaskr.db'
#---------------------------------------------
app=Flask(__name__)
app.config.from_object(__name__)
#---------------------------------------------
defconnect_db():
returnsqlite3.connect(app.config['DATABASE'])
#---------------------------------------------
definit_db():
withclosing(connect_db())asdb:
withapp.open_resource('schema.sql',mode='r')asf:
db.cursor().executescript(f.read())
db.commit()
#---------------------------------------------
init_db()
12 / 20
layout.html
<!doctypehtml>
<title>Flaskr</title>
<linkrel="stylesheet"type="text/css"href="{{url_for('static',filename='style.css')}}"
<divclass="page">
<h1>Flaskr</h1>
<divclass="metanav">
{%ifnotsession.logged_in%}
<ahref="{{url_for('login')}}">login</a>
{%else%}
<ahref="{{url_for('logout')}}">logout</a>
{%endif%}
</div>
{%formessageinget_flashed_messages()%}
<divclass="flash">{{message}}</div>
{%endfor%}
{%blockbody%}{%endblock%}
</div>
flaskr.py
 
13 / 20
importos
fromsqlite3importdbapi2assqlite3
fromflaskimportFlask,request,session,g,redirect,url_for,abort,render_template,flash
#---------------------------------------------
app=Flask(__name__)
#---------------------------------------------
#Loaddefaultconfigandoverrideconfigfromanenvironmentvariable
app.config.update(dict(
DATABASE=os.path.join(app.root_path,'flaskr.db'),
DEBUG=True,
SECRET_KEY='developmentkey',
USERNAME='admin',
PASSWORD='default'
))
app.config.from_envvar('FLASKR_SETTINGS',silent=True)
#---------------------------------------------
defconnect_db():
rv=sqlite3.connect(app.config['DATABASE'])
rv.row_factory=sqlite3.Row
returnrv
#---------------------------------------------
defget_db():
ifnothasattr(g,'sqlite_db'):
g.sqlite_db=connect_db()
returng.sqlite_db
#---------------------------------------------
@app.teardown_appcontext
defclose_db(error):
ifhasattr(g,'sqlite_db'):
g.sqlite_db.close()
flaskr.py
 
14 / 20
flaskr.py
@app.route('/')
defshow_entries():
db=get_db()
cur=db.execute('selecttitle,textfromentriesorderbyiddesc'
entries=cur.fetchall()
returnrender_template('show_entries.html',entries=entries)
#---------------------------------------------
@app.route('/add',methods=['POST'])
defadd_entry():
ifnotsession.get('logged_in'):
abort(401)
db=get_db()
db.execute('insertintoentries(title,text)values(?,?)'
[request.form['title'],request.form['text']])
db.commit()
flash('Newentrywassuccessfullyposted')
returnredirect(url_for('show_entries'))
show_entries.html
{%extends"layout.html"%}
{%blockbody%}
{%ifsession.logged_in%}
<formaction="{{url_for('add_entry')}}"method="post"
<dl>
<dt>Title:
<dd><inputtype="text"size="30"name="title">
<dt>Text:
<dd><tagtextareaname="text"rows="5"cols="40"></tagt
<dd><inputtype="submit"value="Share">
</dl>
</form>
{%endif%}
<ulclass="entries">
{%forentryinentries%}
<li><h2>{{entry.title}}</h2>{{entry.text|safe}}
{%else%}
<li><em>Unbelievable. Noentriesheresofar</em>
{%endfor%}
</ul>
{%endblock%}
15 / 20
flaskr.py
@app.route('/login',methods=['GET','POST'])
deflogin():
error=None
ifrequest.method=='POST':
ifrequest.form['username']!=app.config['USERNAME'
error='Invalidusername'
elifrequest.form['password']!=app.config['PASSWORD'
error='Invalidpassword'
else:
session['logged_in']=True
flash('Youwereloggedin')
returnredirect(url_for('show_entries'))
returnrender_template('login.html',error=error)
#---------------------------------------------
@app.route('/logout')
deflogout():
session.pop('logged_in',None)
flash('Youwereloggedout')
returnredirect(url_for('show_entries'))
#---------------------------------------------
if__name__=='__main__':
app.run()
login.html
{%extends"layout.html"%}
{%blockbody%}
<h2>Login</h2>
{%iferror%}<pclass="error"><strong>Error:</strong>{{er
<formaction="{{url_for('login')}}"method="post">
<dl>
<dt>Username:
<dd><inputtype="text"name="username">
<dt>Password:
<dd><inputtype="password"name="password">
<dd><inputtype="submit"value="Login">
</dl>
</form>
{%endblock%}
16 / 20
test_flaskr.py
py.testtest_flaskr.py
py.testwill run all files in the current directory and its
subdirectories of the form test_*.pyor *_test.py
importpytest
importos
importflaskr
importtempfile
#---------------------------------------------
@pytest.fixture
defclient(request):
db_fd,flaskr.app.config['DATABASE']=tempfile.mkstemp()
flaskr.app.config['TESTING']=True
client=flaskr.app.test_client()
withflaskr.app.app_context():
flaskr.init_db()
defteardown():
os.close(db_fd)
os.unlink(flaskr.app.config['DATABASE'])
request.addfinalizer(teardown)
returnclient
#---------------------------------------------
deflogin(client,username,password):
returnclient.post('/login',data=dict(
username=username,
password=password
),follow_redirects=True)
#---------------------------------------------
deflogout(client):
returnclient.get('/logout',follow_redirects=True)
17 / 20
deftest_empty_db(client):
"""Startwithablankdatabase."""
rv=client.get('/')
assertb'Noentriesheresofar'inrv.data
#---------------------------------------------
deftest_login_logout(client):
"""Makesureloginandlogoutworks"""
rv=login(client,flaskr.app.config['USERNAME'],flaskr.app.config[
assertb'Youwereloggedin'inrv.data
rv=logout(client)
assertb'Youwereloggedout'inrv.data
rv=login(client,flaskr.app.config['USERNAME']+'x',flaskr.app.config[
assertb'Invalidusername'inrv.data
rv=login(client,flaskr.app.config['USERNAME'],flaskr.app.config[
assertb'Invalidpassword'inrv.data
#---------------------------------------------
deftest_messages(client):
"""Testthatmessageswork"""
login(client,flaskr.app.config['USERNAME'],flaskr.app.config[
rv=client.post('/add',data=dict(
title='<Hello>',
text='<strong>HTML</strong>allowedhere'
),follow_redirects=True)
assertb'Noentriesheresofar'notinrv.data
assertb'<Hello>'inrv.data
assertb'<strong>HTML</strong>allowedhere'inrv.data
test_flaskr.py
18 / 20
References
Tutorial - Flask Documentation (0.10)
Flaskr @github
Testing Flask Applications
pytest - Getting Started
19 / 20
ď…“
END
Eueung Mulyana
http://eueung.github.io/python/flask-basics
Python CodeLabs | Attribution-ShareAlike CC BY-SA
20 / 20

Flask Basics