flask intro - rosedu web workshops

24
Flask intro rosedu web workshops 27/03/2013 [email protected] [email protected]

Upload: alex-eftimie

Post on 27-Jan-2015

109 views

Category:

Technology


2 download

DESCRIPTION

The slides we used for a hands on workshop on Flask - micro web framework at http://events.rosedu.org/web-workshops

TRANSCRIPT

Page 1: Flask intro - ROSEdu web workshops

Flask introrosedu web workshops

27/03/2013 [email protected] [email protected]

Page 2: Flask intro - ROSEdu web workshops

prerequisites ● python

● bash

● HTTP

● set-up a working environment

● run a local server

● write a twitter clone in a single

python file

● use templates

● use an ORM

what we'll do

Page 3: Flask intro - ROSEdu web workshops

was ist flask?● micro web framework

● WSGI (same as django, webapp2)

● decoupled

● werkzeug routing

● jinja2 templates

● wtf forms

● many extensions

● write web applications not web scripts (such as PHP does)

Page 4: Flask intro - ROSEdu web workshops

virtualenv, pip# install system-wideapt-get install python-virtualenv# create newvirtualenv env# activatesource env/bin/activate# install flaskpip install flask

# pip freezepip freeze > requirements.txt

Page 5: Flask intro - ROSEdu web workshops

basic flask app#!/usr/bin/env python

import flask

app = flask.Flask(__name__)app.config['DEBUG'] = True

@app.route('/')def home(): return "Hello World!"

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

(env)student@intel:~$ python mini.py * Running on http://127.0.0.1:5000/

127.0.0.1 - - [27/Mar/2013 01:13:28] "GET / HTTP/1.1" 200 -

Page 6: Flask intro - ROSEdu web workshops

new message form● create a file new.html inside a templates/ folder

● route /new to a view function rendering the template

...return flask.render_template('new.html')

(see home())

<h1>New message</h1>

<form method="post"> <textarea rows="4" cols="80" name="message"></textarea>

<br> <button type="submit">send</button></form>

Page 7: Flask intro - ROSEdu web workshops

form submit; redirect ● check request method (one of 'GET' or 'POST')

flask.request.method == 'POST'

● get post data, print it

print flask.request.form['message']

● redirect to home page

flask.redirect(flask.url_for('home'))

@app.route('/new', methods=['GET', 'POST'])def new():

if flask.request.method == 'POST':print "msg:", flask.request.form['message']return flask.redirect(flask.url_for('home'))

return flask.render_template('new.html')

Page 8: Flask intro - ROSEdu web workshops

db; message model● in a terminal:pip install SQLAlchemy Flask-SQLAlchemy

● in mini.py

from flask.ext.sqlalchemy import SQLAlchemy...app.config['SQLALCHEMY_DATABASE_URI' ] = 'sqlite:////tmp/test.db'db = SQLAlchemy(app)...

class Message(db.Model): id = db.Column(db.Integer, primary_key =True) text = db.Column(db.String) time = db.Column(db.DateTime)

Page 9: Flask intro - ROSEdu web workshops

save to db● create db before app.run()

db.create_all()

● replace print with insert statement, in new()text = flask.request.form[ 'message']message = Message(text=text, time=datetime.utcnow())db.session.add(message)db.session.commit()

● sqlite3 /tmp/test.db 'select * from message'

Page 10: Flask intro - ROSEdu web workshops

fetch from db● change print "Hello World" with

template rendering and context

flask.render_template( 'messages.html',

messages=Message.query.all())

● create html file in templates/

● use {{ variable }} to display

variable value in template

● call url_for for view permalink

● use {% for %} to iterate through

messages

messages.html

<h1>Mini Twitter</h1>

<p> <a href="{{ url_for('new') }}" >new msg</a></p>

{% for message in messages %}<article> <p>{{ message.text }} </p> <footer>

<time>{{message.time}} </time> </footer></article>{% endfor %}

Page 11: Flask intro - ROSEdu web workshops

template filtersUsage:{{ variable|filter }}

Custom:@app.template_filter()def tolower(value): return value.lower()

You:● display message time in local

time

Page 12: Flask intro - ROSEdu web workshops

common layout templatelayout.html

<!doctype html>

<html>

...

{% block content %}

{% endblock %}

</html>

messages.html{% extends 'layout.html' %}

{% block content %}

goodies...

{% endblock %}

Page 13: Flask intro - ROSEdu web workshops

config file● move configuration to a file

app.config.from_pyfile('settings.py')

● settings

DEBUG = True

...

Page 14: Flask intro - ROSEdu web workshops

flash messages● use session to display messages in the next view

flask.flash("I have a message for you" )

● display messages in template {% for message in get_flashed_messages() %}

<p class="msg"> ... {% endfor %}

● put it in header.html then include it before content block in the layout

template

{% include 'other_template.html' %}

Page 15: Flask intro - ROSEdu web workshops

login● view + template the same as new() - new.html

● handle the submitted usernameif flask.request.method == 'POST':

username = flask.request.form['username']...

● print username or flash it

{% extends 'layout.html' %}

{% block content %} <form method="post"> <input name="username"> <button type="submit">login</button> </form>{% endblock %}

Page 16: Flask intro - ROSEdu web workshops

session● store something in session

flask.session['username'] = username

● fetch and expose in [email protected]_requestdef get_user(): flask.g.username = flask.session.get('username')

● use in header{% if g.username %} logged in as {{ g.username }}{% else %} <a href="{{ url_for('login') }}" >login</a>{% endif %}

Page 17: Flask intro - ROSEdu web workshops

logout● clean the session in style

flask.session.pop('variable', '')

● you○ write a view logout()

○ route /logout to it

○ delete username from session

○ flash the message "bye bye"

○ redirect to home page

○ link to it in header

Page 18: Flask intro - ROSEdu web workshops

login required decorator● redirect to login if not authenticated

def login_required(func): @wraps(func) def wrapper(*args, **kwargs): if flask.g.username is None: return flask.redirect('login') return func(*args, **kwargs) return wrapper

[email protected]('/private')

@login_required

def private_view():...

● you: decorate new()

Page 19: Flask intro - ROSEdu web workshops

person model● db model with id (Integer, primary_key) and username

(String)

● message authorclass Message(db.Model):

...person_id = db.Column(db.Integer, db.ForeignKey('person.id'))person = db.relationship('Person',

backref=db.backref('messages', lazy='dynamic'))

● get or create Person@classmethod

def get_or_create(cls, username): person = cls.query.filter_by(username =username).first() if person is None: person = cls(username=username)

...

Page 20: Flask intro - ROSEdu web workshops

message and person● when adding a message to db

text = flask.request.form['message']person = Person.get_or_create(flask .g.username)message = Message(text=text, time=datetime.utcnow(), person=person)

● when displaying in template<p>

<strong>{{ message.person.username }}: </strong>{{ message.text }}

</p>

Page 21: Flask intro - ROSEdu web workshops

person and messages● add view for a person's feed

● route it to /<username>@app.route('/<username>')

● get person or raise http 404 person = Person.query.filter_by(username =username).first_or_404()

● display messages in template

flask.render_template('messages.html', messages=person.messages)

● show link to person's feed...{% set username = message.person.username %}{% set url = url_for('person_feed', username=username) %}<strong><a href="{{ url }}">{{ username }}</a>:</strong>...

Page 22: Flask intro - ROSEdu web workshops

static assets● create a folder static/

● add style.css and some ninja CSS

● link to it in layout.html

<link rel="stylesheet" href="{{ url_for('static', filename='style.css')

}}">

● wrap {% block content %} in <div class="container"> </div>/* style.css */

* { font-family: Ubuntu, arial }body { background-color: #efefef }.container { width: 800px; margin: 0 auto; background-color: #fff; }p.msg { background-color: #99ff99; border-radius: 20px; border: 1px solid green; color: green: }a { text-decoration: none }

Page 23: Flask intro - ROSEdu web workshops

wrapping upwe learned about:

● web application

● url routing

● templates

● sql

● sessions

next:

● deployment options

● security, social extensions

file structure:

mini.py

settings.py

static/

style.css

templates/

header.html

layout.html

messages.html

new.html

Page 24: Flask intro - ROSEdu web workshops

see more

● full source codehttps://github.com/mgax/minitwitter

● flask documentationhttp://flask.pocoo.org/docs/