Slide 1

Slide 1 text

DOING MORE WITH LESS Large Scale Apps with FLASK Friday, 2 March, 12

Slide 2

Slide 2 text

Pocoo Friday, 2 March, 12

Slide 3

Slide 3 text

Friday, 2 March, 12

Slide 4

Slide 4 text

JINJA FLASK PYGMENTS WERKZEUGSPHINX ... Friday, 2 March, 12

Slide 5

Slide 5 text

MICROFramework Friday, 2 March, 12

Slide 6

Slide 6 text

MICRO Friday, 2 March, 12

Slide 7

Slide 7 text

Database Abstraction Friday, 2 March, 12

Slide 8

Slide 8 text

Database Abstraction Friday, 2 March, 12

Slide 9

Slide 9 text

Form Validation Friday, 2 March, 12

Slide 10

Slide 10 text

Form Validation Friday, 2 March, 12

Slide 11

Slide 11 text

Django-ish Admin Friday, 2 March, 12

Slide 12

Slide 12 text

Django-ish Admin Friday, 2 March, 12

Slide 13

Slide 13 text

Jinja 2 Werkzeug & Friday, 2 March, 12

Slide 14

Slide 14 text

Templating WSGI & Friday, 2 March, 12

Slide 15

Slide 15 text

Tools Friday, 2 March, 12

Slide 16

Slide 16 text

Friday, 2 March, 12

Slide 17

Slide 17 text

gunicorn Friday, 2 March, 12

Slide 18

Slide 18 text

gunicorn gevent Friday, 2 March, 12

Slide 19

Slide 19 text

gunicorn gevent nginx Friday, 2 March, 12

Slide 20

Slide 20 text

Friday, 2 March, 12

Slide 21

Slide 21 text

unittest2/nose Friday, 2 March, 12

Slide 22

Slide 22 text

unittest2/nose lettuce Friday, 2 March, 12

Slide 23

Slide 23 text

Friday, 2 March, 12

Slide 24

Slide 24 text

fabric Friday, 2 March, 12

Slide 25

Slide 25 text

fabric virtualenv Friday, 2 March, 12

Slide 26

Slide 26 text

fabric virtualenv jenkins Friday, 2 March, 12

Slide 27

Slide 27 text

RESTful/ish APIs Friday, 2 March, 12

Slide 28

Slide 28 text

Warning CODE BEYOND THIS POINT Friday, 2 March, 12

Slide 29

Slide 29 text

Friday, 2 March, 12

Slide 30

Slide 30 text

from flask import Flask Friday, 2 March, 12

Slide 31

Slide 31 text

from flask import Flask app = Flask(__name__) Friday, 2 March, 12

Slide 32

Slide 32 text

from flask import Flask app = Flask(__name__) @app.route("/") Friday, 2 March, 12

Slide 33

Slide 33 text

from flask import Flask app = Flask(__name__) @app.route("/") def hello(): Friday, 2 March, 12

Slide 34

Slide 34 text

from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!" Friday, 2 March, 12

Slide 35

Slide 35 text

from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!" if __name__ == "__main__": Friday, 2 March, 12

Slide 36

Slide 36 text

from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!" if __name__ == "__main__": app.run() Friday, 2 March, 12

Slide 37

Slide 37 text

$ pythonhello.py Friday, 2 March, 12

Slide 38

Slide 38 text

Werkzeug Router Friday, 2 March, 12

Slide 39

Slide 39 text

Friday, 2 March, 12

Slide 40

Slide 40 text

@app.route(‘/’) Friday, 2 March, 12

Slide 41

Slide 41 text

@app.route(‘/dashboard’) @app.route(‘/’) Friday, 2 March, 12

Slide 42

Slide 42 text

@app.route(‘/dashboard’) @app.route(‘/’) @app.route(‘/pages/’) Friday, 2 March, 12

Slide 43

Slide 43 text

@app.route(‘/dashboard’) @app.route(‘/’) @app.route(‘/pages/’) @app.route(‘/user/’) Friday, 2 March, 12

Slide 44

Slide 44 text

@app.route(‘/dashboard’) @app.route(‘/’) @app.route(‘/pages/’) @app.route(‘/user/’) @app.route(‘/posts//’) Friday, 2 March, 12

Slide 45

Slide 45 text

@app.route(‘/dashboard’) @app.route(‘/’) @app.route(‘/pages/’) @app.route(‘/user/’) @app.route(‘/posts//’) @app.route(‘/’) Friday, 2 March, 12

Slide 46

Slide 46 text

Custom Converters Friday, 2 March, 12

Slide 47

Slide 47 text

from werkzeug.routing import BaseConverter class ListConverter(BaseConverter): def to_python(self, value): return value.split(',') def to_url(self, values): return ','.join(BaseConverter.to_url(value) for value in values) app = Flask(__name__) app.url_map.converters['list'] = ListConverter Friday, 2 March, 12

Slide 48

Slide 48 text

Testing Friday, 2 March, 12

Slide 49

Slide 49 text

Friday, 2 March, 12

Slide 50

Slide 50 text

UNITTEST FACTORY_BOY LETTUCE NOSEMOCK ... Friday, 2 March, 12

Slide 51

Slide 51 text

Friday, 2 March, 12

Slide 52

Slide 52 text

Thread/Context Locals Friday, 2 March, 12

Slide 53

Slide 53 text

with app.test_request_context('/posts?sort=asc&limit=10'): Friday, 2 March, 12

Slide 54

Slide 54 text

with app.test_client() as client: result = client.get('/posts?sort=asc&limit=10') Friday, 2 March, 12

Slide 55

Slide 55 text

Useful Extensions Friday, 2 March, 12

Slide 56

Slide 56 text

Friday, 2 March, 12

Slide 57

Slide 57 text

Flask-Login Friday, 2 March, 12

Slide 58

Slide 58 text

Flask-Login Flask-Testing Friday, 2 March, 12

Slide 59

Slide 59 text

Flask-Login Flask-Testing Flask-WTForms Friday, 2 March, 12

Slide 60

Slide 60 text

Flask-Login Flask-Testing Flask-WTForms Flask-Bcrypt Friday, 2 March, 12

Slide 61

Slide 61 text

Flask-Login Flask-Testing Flask-WTForms Flask-Bcrypt Flask-Assets Friday, 2 March, 12

Slide 62

Slide 62 text

ORM Integration Friday, 2 March, 12

Slide 63

Slide 63 text

Friday, 2 March, 12

Slide 64

Slide 64 text

SQLAlchemy Friday, 2 March, 12

Slide 65

Slide 65 text

SQLAlchemy MongoKit Friday, 2 March, 12

Slide 66

Slide 66 text

SQLAlchemy MongoKit Pycassa Friday, 2 March, 12

Slide 67

Slide 67 text

SQLAlchemy MongoKit Pycassa CouchDB Friday, 2 March, 12

Slide 68

Slide 68 text

from flask import Flask from flaskext.sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' db = SQLAlchemy(app) class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True) email = db.Column(db.String(120), unique=True) def __init__(self, username, email): self.username = username self.email = email def __repr__(self): return '' % self.username Friday, 2 March, 12

Slide 69

Slide 69 text

from flask import Flask from mongokit import Connection, Document # configuration MONGODB_HOST = 'localhost' MONGODB_PORT = 27017 # create the little application object app = Flask(__name__) app.config.from_object(__name__) # connect to the database connection = Connection(app.config['MONGODB_HOST'], app.config['MONGODB_PORT']) Friday, 2 March, 12

Slide 70

Slide 70 text

class Post(Document): structure = { 'title':unicode, 'body':unicode, 'author':unicode, 'date_creation':datetime.datetime, 'rank':int, 'tags': [unicode], } required_fields = ['title','author', 'date_creation'] default_values = {'rank':0, 'date_creation': datetime.datetime.utcnow} Friday, 2 March, 12

Slide 71

Slide 71 text

Callbacks/hooks Friday, 2 March, 12

Slide 72

Slide 72 text

Friday, 2 March, 12

Slide 73

Slide 73 text

@app.before_request Friday, 2 March, 12

Slide 74

Slide 74 text

@app.before_request @app.after_request Friday, 2 March, 12

Slide 75

Slide 75 text

@app.before_request @app.after_request @app.before_first_request Friday, 2 March, 12

Slide 76

Slide 76 text

@app.before_request @app.after_request @app.before_first_request @app.errorhandler Friday, 2 March, 12

Slide 77

Slide 77 text

@app.before_request @app.after_request @app.before_first_request @app.errorhandler ... Friday, 2 March, 12

Slide 78

Slide 78 text

Signals via Blinker Friday, 2 March, 12

Slide 79

Slide 79 text

Friday, 2 March, 12

Slide 80

Slide 80 text

flask.template_rendered Friday, 2 March, 12

Slide 81

Slide 81 text

flask.request_started flask.template_rendered Friday, 2 March, 12

Slide 82

Slide 82 text

flask.request_started flask.request_finished flask.template_rendered Friday, 2 March, 12

Slide 83

Slide 83 text

flask.request_started flask.request_finished flask.template_rendered flask.got_request_exception Friday, 2 March, 12

Slide 84

Slide 84 text

flask.request_started flask.request_finished flask.template_rendered flask.got_request_exception flask.request_tearing_down Friday, 2 March, 12

Slide 85

Slide 85 text

In-process event dispatching Friday, 2 March, 12

Slide 86

Slide 86 text

Not the same as callbacks/hooks Friday, 2 March, 12

Slide 87

Slide 87 text

API Design Friday, 2 March, 12

Slide 88

Slide 88 text

Start thinking in terms of datastructures Friday, 2 March, 12

Slide 89

Slide 89 text

And breaking up your application in to services Friday, 2 March, 12

Slide 90

Slide 90 text

Instead of staying in the MVC Bubble. Friday, 2 March, 12

Slide 91

Slide 91 text

Blueprints Friday, 2 March, 12

Slide 92

Slide 92 text

from flask import Blueprint, render_template, abort from jinja2 import TemplateNotFound static_page = Blueprint('static_page', __name__, template_folder='templates') @static_page.route('/') def show(page): try: return render_template('pages/%s.html' % page) except TemplateNotFound: abort(404) Friday, 2 March, 12

Slide 93

Slide 93 text

from flask import Flask from myapp.static_page import static_page app = Flask(__name__) app.register_blueprint(static_page, url_prefix= ‘/pages’) Friday, 2 March, 12

Slide 94

Slide 94 text

Blueprints have their own templates, static files, and callbacks/hooks. Friday, 2 March, 12

Slide 95

Slide 95 text

Pluggable Views Friday, 2 March, 12

Slide 96

Slide 96 text

@app.route('/users/') def show_users(page): users = User.query.all() return render_template('users.html', users=users) Friday, 2 March, 12

Slide 97

Slide 97 text

from flask.views import View class ShowUsers(View): def dispatch_request(self): users = User.query.all() return render_template('users.html', objects=users) app.add_url_rule('/users/', ShowUsers.as_view('show_users')) Friday, 2 March, 12

Slide 98

Slide 98 text

from flask.views import View class ListView(View): def get_template_name(self): raise NotImplementedError() def render_template(self, context): return render_template(self.get_template_name(), **context) def dispatch_request(self): context = {'objects': self.get_objects()} return self.render_template(context) class UserView(ListView): def get_template_name(self): return 'users.html' def get_objects(self): return User.query.all() Friday, 2 March, 12

Slide 99

Slide 99 text

Method-Based Dispatching Friday, 2 March, 12

Slide 100

Slide 100 text

from flask.views import MethodView class User(MethodView): def get(self): users = User.query.all() ... def post(self): user = User.from_form_data(request.form) ... app.add_url_rule('/users/', view_func=User.as_view('users')) Friday, 2 March, 12

Slide 101

Slide 101 text

QUESTIONS? Friday, 2 March, 12

Slide 102

Slide 102 text

Fictive Kin Friday, 2 March, 12

Slide 103

Slide 103 text

@jperras Joël Perras http://nerderati.com Friday, 2 March, 12