SlideShare a Scribd company logo
1 of 43
Download to read offline
Advanced Flask Patterns
                      PyCon Russia 2013

    — a presentation by Armin Ronacher
                              @mitsuhiko
-1   Who am I?
That's me
✤ Armin Ronacher

✤ @mitsuhiko

✤ Creator of Flask/Werkzeug/Jinja2
0   Focus & Caveats
Interrupt me
✤ Assumes some sense of Flask knowledge

✤ If too fast, interrupt me

✤ If not detailed enough, let me know
1   State Management
Flask States


✤ Setup State

✤ Application Context Bound

✤ Request Context Bound
Setup State



>>> from flask import g
>>> g.foo = 42
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: working outside of application context
Application Bound


>>>   ctx = app.app_context()
>>>   ctx.push()
>>>   g.foo = 42
>>>   g.foo
42

>>> from flask import request
>>> request.args
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: working outside of request context
Request Bound


>>> ctx = app.test_request_context()
>>> ctx.push()
>>> request.url
'http://localhost/'
>>> g.foo = 42
>>> g.foo
42
Lifetimes


✤ flask.current_app ⇝ application context

✤ flask.g ⇝ application context (as of 0.10)

✤ flask.request ⇝ request context

✤ flask.session ⇝ request context
Quick Overview


✤ Application contexts are fast to create/destroy

✤ Pushing request context pushes new application context

✤ Flask 0.10 binds g to the application context

✤ Bind resources to the application context
2   Resource Management
Basic Guide


✤ Create/Destroy Application Context == Task

✤ Bind resources task wise

✤ Resources: claimed database connections, caches
Teardown Illustrated
>>>   from flask import Flask
>>>   app = Flask(__name__)
>>>   @app.teardown_appcontext
...   def called_on_teardown(error=None):
...     print 'Tearing down, error:', error
...

>>> ctx = app.app_context()
>>> ctx.push()
>>>
>>> ctx.pop()
Tearing down, error: None

>>> with app.app_context():
... 1/0
...
Tearing down, error: integer division or modulo by zero
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: integer division or modulo by zero
Resource Management

def get_database_connection():
    con = getattr(g, 'database_connection', None)
    if con is None:
        g.con = con = connection_pool.get_connection()
    return con


@app.teardown_appcontext
def return_database_connection(error=None):
    con = getattr(g, 'database_connection', None)
    if con is not None:
        connection_pool.release_connection(con)
Responsive Resources


@app.teardown_appcontext
def return_database_connection(error=None):
    con = getattr(g, 'database_connection', None)
    if con is None:
        return
    if error is None:
        con.commit()
    else:
        con.rollback()
    connection_pool.release_connection(con)
Per-Task Callbacks



def after_commit(f):
    callbacks = getattr(g, 'on_commit_callbacks', None)
    if callbacks is None:
        g.on_commit_callbacks = callbacks = []
    callbacks.append(f)
    return f
Per-Task Callbacks

@app.teardown_appcontext
def return_database_connection(error=None):
    con = getattr(g, 'database_connection', None)
    if con is None:
        return
    if error is None:
        con.commit()
        callbacks = getattr(g, 'on_commit_callbacks', ())
        for callback in callbacks:
            callback()
    else:
        con.rollback()
    connection_pool.release_connection(con)
Per-Task Callbacks Example


def purchase_product(product, user):
    user.purchased_products.append(product)
    @after_commit
    def send_success_mail():
        body = render_template('mails/product_purchased.txt',
            user=user,
            product=product
        )
        send_mail(user.email_address, 'Product Purchased', body)
3   Response Creation
Response Object Passing


✤ One request object: read only

✤ Potentially many response objects, passed down a stack

✤ … can be implicitly created

✤ … can be replaced by other response objects

✤ there is no flask.response!
Implicit Response Creation



@app.route('/')
def index():
    return render_template('index.html')
Explicit Creation


from flask import make_response


@app.route('/')
def index():
    body = render_template('index.html')
    response = make_response(body)
    response.headers['X-Powered-By'] = 'Not-PHP/1.0'
    return response
Customized Creation


from flask import Flask, jsonify


class CustomFlask(Flask):

    def make_response(self, rv):
        if hasattr(rv, 'to_json'):
            return jsonify(rv.to_json())
        return Flask.make_response(self, rv)
Customized Creation Example
class User(object):

    def __init__(self, id, username):
        self.id = id
        self.username = username

    def to_json(self):
        return {
            'id': self.id,
            'username': self.username
        }


app = CustomFlask(__name__)

@app.route('/')
def index():
    return User(42, 'john')
4   Server Sent Events
Basic Overview


✤ Open Socket

✤ Sends "data: <data>rnrn" packets

✤ Good idea for gevent/eventlet, bad idea for kernel level concurrency
Subscribing
from redis import Redis
from flask import Response, stream_with_context


redis = Redis()


@app.route('/streams/interesting')
def stream():
    def generate():
        pubsub = redis.pubsub()
        pubsub.subscribe('interesting-channel')
        for event in pubsub.listen():
            if event['type'] == 'message':
                yield 'data: %srnrn' % event['data']
    return Response(stream_with_context(generate()),
                    direct_passthrough=True,
                    mimetype='text/event-stream')
Publishing


from flask import json, redirect, url_for


@app.route('/create-something', methods=['POST'])
def create_something():
    create_that_thing()
    redis.publish('interesting-channel', json.dumps({
        'event': 'created',
        'kind': 'something'
    }))
    return redirect(url_for('index'))
Don't be Afraid of Proxying


✤ gunicorn/uwsgi blocking for main app

✤ gunicorn gevent for SSE

✤ nginx for unification
5   Worker Separation
supervisor config



[program:worker-blocking]
command=gunicorn -w 4 yourapplication:app -b 0.0.0.0:8000

[program:worker-nonblocking]
command=gunicorn -k gevent -w 4 yourapplication:app -b 0.0.0.0:8001
nginx config

server {
    listen 80;
    server_name example.com;

    location /streams {
        proxy_set_header Host $http_host;
        proxy_pass http://localhost:8001/streams;
    }

    location / {
        proxy_set_header Host $http_host;
        proxy_pass http://localhost:8000/;
    }
}
6   Signing Stuff
Basic Overview


✤ Use itsdangerous for signing information that roundtrips

✤ Saves you from storing information in a database

✤ Especially useful for small pieces of information that need to stay
  around for long (any form of token etc.)
User Activation Example
from flask import abort
import itsdangerous


serializer = itsdangerous .URLSafeSerializer(secret_key=app.config['SECRET_KEY'])
ACTIVATION_SALT = 'x7fxfbxc2(;rxa8Ox16{'


def get_activation_link(user):
    return url_for('activate', code=serializer.dumps(user.user_id, salt=ACTIVATION_SALT))


@app.route('/activate/<code>')
def activate(code):
    try:
         user_id = serializer.loads(code, salt=ACTIVATION_SALT)
    except itsdangerous.BadSignature:
         abort(404)
    activate_the_user_with_id(user_id)
7   Customization
Simple Cache Busting

from hashlib import md5
import pkg_resources


ASSET_REVISION = md5(str(pkg_resources.get_distribution(
    'Package-Name').version)).hexdigest())[:14]


@app.url_defaults
def static_cache_buster(endpoint, values):
    if endpoint == 'static':
        values['_v'] = ASSET_REVISION
Disable Parsing


from flask import Flask, Request


class SimpleRequest(Request):
    want_form_data_parsed = False
    data = None


app = Flask(__name__)
app.request_class = SimpleRequest
8   Secure Redirects
Redirect Back
from urlparse import urlparse, urljoin

def is_safe_url(target):
    ref_url = urlparse(request.host_url)
    test_url = urlparse(urljoin(request.host_url, target))
    return test_url.scheme in ('http', 'https') and 
           ref_url.netloc == test_url.netloc

def is_different_url(url):
    this_parts = urlparse(request.url)
    other_parts = urlparse(url)
    return this_parts[:4] != other_parts[:4] and 
        url_decode(this_parts.query) != url_decode(other_parts.query)

def redirect_back(fallback):
    next = request.args.get('next') or request.referrer
    if next and is_safe_url(next) and is_different_url(next):
        return redirect(next)
    return redirect(fallback)
Q&A
 http://fireteam.net/ — Armin Ronacher — @mitsuhiko

More Related Content

What's hot

Web develop in flask
Web develop in flaskWeb develop in flask
Web develop in flaskJim Yeh
 
Flask RESTful Flask HTTPAuth
Flask RESTful Flask HTTPAuthFlask RESTful Flask HTTPAuth
Flask RESTful Flask HTTPAuthEueung Mulyana
 
Build restful ap is with python and flask
Build restful ap is with python and flaskBuild restful ap is with python and flask
Build restful ap is with python and flaskJeetendra singh
 
Flask Introduction - Python Meetup
Flask Introduction - Python MeetupFlask Introduction - Python Meetup
Flask Introduction - Python MeetupAreski Belaid
 
Python RESTful webservices with Python: Flask and Django solutions
Python RESTful webservices with Python: Flask and Django solutionsPython RESTful webservices with Python: Flask and Django solutions
Python RESTful webservices with Python: Flask and Django solutionsSolution4Future
 
Flask restfulservices
Flask restfulservicesFlask restfulservices
Flask restfulservicesMarcos Lin
 
Learn flask in 90mins
Learn flask in 90minsLearn flask in 90mins
Learn flask in 90minsLarry Cai
 
BUILDING MODERN PYTHON WEB FRAMEWORKS USING FLASK WITH NEIL GREY
BUILDING MODERN PYTHON WEB FRAMEWORKS USING FLASK WITH NEIL GREYBUILDING MODERN PYTHON WEB FRAMEWORKS USING FLASK WITH NEIL GREY
BUILDING MODERN PYTHON WEB FRAMEWORKS USING FLASK WITH NEIL GREYCodeCore
 
Quick flask an intro to flask
Quick flask   an intro to flaskQuick flask   an intro to flask
Quick flask an intro to flaskjuzten
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Elena Kolevska
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101Samantha Geitz
 
Building a Dynamic Website Using Django
Building a Dynamic Website Using DjangoBuilding a Dynamic Website Using Django
Building a Dynamic Website Using DjangoNathan Eror
 
8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rackdanwrong
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design PatternsBobby Bouwmann
 
Python Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CIPython Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CIBruno Rocha
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
 

What's hot (20)

Web develop in flask
Web develop in flaskWeb develop in flask
Web develop in flask
 
Flask RESTful Flask HTTPAuth
Flask RESTful Flask HTTPAuthFlask RESTful Flask HTTPAuth
Flask RESTful Flask HTTPAuth
 
Build restful ap is with python and flask
Build restful ap is with python and flaskBuild restful ap is with python and flask
Build restful ap is with python and flask
 
Flask Introduction - Python Meetup
Flask Introduction - Python MeetupFlask Introduction - Python Meetup
Flask Introduction - Python Meetup
 
Python RESTful webservices with Python: Flask and Django solutions
Python RESTful webservices with Python: Flask and Django solutionsPython RESTful webservices with Python: Flask and Django solutions
Python RESTful webservices with Python: Flask and Django solutions
 
Flask SQLAlchemy
Flask SQLAlchemy Flask SQLAlchemy
Flask SQLAlchemy
 
Flask restfulservices
Flask restfulservicesFlask restfulservices
Flask restfulservices
 
Learn flask in 90mins
Learn flask in 90minsLearn flask in 90mins
Learn flask in 90mins
 
BUILDING MODERN PYTHON WEB FRAMEWORKS USING FLASK WITH NEIL GREY
BUILDING MODERN PYTHON WEB FRAMEWORKS USING FLASK WITH NEIL GREYBUILDING MODERN PYTHON WEB FRAMEWORKS USING FLASK WITH NEIL GREY
BUILDING MODERN PYTHON WEB FRAMEWORKS USING FLASK WITH NEIL GREY
 
Quick flask an intro to flask
Quick flask   an intro to flaskQuick flask   an intro to flask
Quick flask an intro to flask
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
Getting Started-with-Laravel
Getting Started-with-LaravelGetting Started-with-Laravel
Getting Started-with-Laravel
 
Rest api with Python
Rest api with PythonRest api with Python
Rest api with Python
 
Laravel 5
Laravel 5Laravel 5
Laravel 5
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101
 
Building a Dynamic Website Using Django
Building a Dynamic Website Using DjangoBuilding a Dynamic Website Using Django
Building a Dynamic Website Using Django
 
8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rack
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design Patterns
 
Python Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CIPython Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CI
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 

Viewers also liked

Build website in_django
Build website in_django Build website in_django
Build website in_django swee meng ng
 
Quokka CMS - Desenvolvendo web apps com Flask e MongoDB - grupy - Outubro 2015
Quokka CMS - Desenvolvendo web apps com Flask e MongoDB - grupy - Outubro 2015Quokka CMS - Desenvolvendo web apps com Flask e MongoDB - grupy - Outubro 2015
Quokka CMS - Desenvolvendo web apps com Flask e MongoDB - grupy - Outubro 2015Bruno Rocha
 
webアプリケーションフレームワークの話
webアプリケーションフレームワークの話webアプリケーションフレームワークの話
webアプリケーションフレームワークの話Yoshihiro Ura
 
Webアプリケーションフレームワーク flask
Webアプリケーションフレームワーク flaskWebアプリケーションフレームワーク flask
Webアプリケーションフレームワーク flaskXMLProJ2014
 
Flask Full Stack - Desenvolvendo um CMS com Flask e MongoDB
Flask Full Stack - Desenvolvendo um CMS com Flask e MongoDBFlask Full Stack - Desenvolvendo um CMS com Flask e MongoDB
Flask Full Stack - Desenvolvendo um CMS com Flask e MongoDBBruno Rocha
 
Writing your first web app using Python and Flask
Writing your first web app using Python and FlaskWriting your first web app using Python and Flask
Writing your first web app using Python and FlaskDanielle Madeley
 
Introduction to Google App Engine with Python
Introduction to Google App Engine with PythonIntroduction to Google App Engine with Python
Introduction to Google App Engine with PythonBrian Lyttle
 
Flask入門
Flask入門Flask入門
Flask入門aoshiman
 
Making use of OpenStreetMap data with Python
Making use of OpenStreetMap data with PythonMaking use of OpenStreetMap data with Python
Making use of OpenStreetMap data with PythonAndrii Mishkovskyi
 
Thermo Electric Converter
Thermo Electric ConverterThermo Electric Converter
Thermo Electric ConverterMakeNET
 
Modes of heat transfer
Modes of heat transferModes of heat transfer
Modes of heat transferRIFFAT_ZAHID
 
OpenStreetMap in 3D using Python
OpenStreetMap in 3D using PythonOpenStreetMap in 3D using Python
OpenStreetMap in 3D using PythonMartin Christen
 

Viewers also liked (17)

Build website in_django
Build website in_django Build website in_django
Build website in_django
 
Quokka CMS - Desenvolvendo web apps com Flask e MongoDB - grupy - Outubro 2015
Quokka CMS - Desenvolvendo web apps com Flask e MongoDB - grupy - Outubro 2015Quokka CMS - Desenvolvendo web apps com Flask e MongoDB - grupy - Outubro 2015
Quokka CMS - Desenvolvendo web apps com Flask e MongoDB - grupy - Outubro 2015
 
webアプリケーションフレームワークの話
webアプリケーションフレームワークの話webアプリケーションフレームワークの話
webアプリケーションフレームワークの話
 
aiohttp intro
aiohttp introaiohttp intro
aiohttp intro
 
Rest in flask
Rest in flaskRest in flask
Rest in flask
 
Webアプリケーションフレームワーク flask
Webアプリケーションフレームワーク flaskWebアプリケーションフレームワーク flask
Webアプリケーションフレームワーク flask
 
Flask Full Stack - Desenvolvendo um CMS com Flask e MongoDB
Flask Full Stack - Desenvolvendo um CMS com Flask e MongoDBFlask Full Stack - Desenvolvendo um CMS com Flask e MongoDB
Flask Full Stack - Desenvolvendo um CMS com Flask e MongoDB
 
Python and GIS
Python and GISPython and GIS
Python and GIS
 
Writing your first web app using Python and Flask
Writing your first web app using Python and FlaskWriting your first web app using Python and Flask
Writing your first web app using Python and Flask
 
Introduction to Google App Engine with Python
Introduction to Google App Engine with PythonIntroduction to Google App Engine with Python
Introduction to Google App Engine with Python
 
Flask入門
Flask入門Flask入門
Flask入門
 
Flask勉強会その1
Flask勉強会その1Flask勉強会その1
Flask勉強会その1
 
Making use of OpenStreetMap data with Python
Making use of OpenStreetMap data with PythonMaking use of OpenStreetMap data with Python
Making use of OpenStreetMap data with Python
 
Thermo Electric Converter
Thermo Electric ConverterThermo Electric Converter
Thermo Electric Converter
 
Modes of transfer of heat
Modes of transfer of heatModes of transfer of heat
Modes of transfer of heat
 
Modes of heat transfer
Modes of heat transferModes of heat transfer
Modes of heat transfer
 
OpenStreetMap in 3D using Python
OpenStreetMap in 3D using PythonOpenStreetMap in 3D using Python
OpenStreetMap in 3D using Python
 

Similar to Flask patterns

Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsMichael Peacock
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesLindsay Holmwood
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveJeff Smith
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Hugo Hamon
 
PyCon US 2012 - State of WSGI 2
PyCon US 2012 - State of WSGI 2PyCon US 2012 - State of WSGI 2
PyCon US 2012 - State of WSGI 2Graham Dumpleton
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenchesLukas Smith
 
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiJérémy Derussé
 
Denys Serhiienko "ASGI in depth"
Denys Serhiienko "ASGI in depth"Denys Serhiienko "ASGI in depth"
Denys Serhiienko "ASGI in depth"Fwdays
 
Debugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionDebugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionIan Barber
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the TrenchesJonathan Wage
 
And the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportAnd the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportBen Scofield
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Jakub Zalas
 
Debugging: Rules & Tools
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & ToolsIan Barber
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applicationschartjes
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the FinishYehuda Katz
 
Hidden Docs in Angular
Hidden Docs in AngularHidden Docs in Angular
Hidden Docs in AngularYadong Xie
 
Projeto-web-services-Spring-Boot-JPA.pdf
Projeto-web-services-Spring-Boot-JPA.pdfProjeto-web-services-Spring-Boot-JPA.pdf
Projeto-web-services-Spring-Boot-JPA.pdfAdrianoSantos888423
 
Heavy Web Optimization: Backend
Heavy Web Optimization: BackendHeavy Web Optimization: Backend
Heavy Web Optimization: BackendVõ Duy Tuấn
 
Tasks: you gotta know how to run them
Tasks: you gotta know how to run themTasks: you gotta know how to run them
Tasks: you gotta know how to run themFilipe Ximenes
 

Similar to Flask patterns (20)

Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websites
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more Reactive
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
 
PyCon US 2012 - State of WSGI 2
PyCon US 2012 - State of WSGI 2PyCon US 2012 - State of WSGI 2
PyCon US 2012 - State of WSGI 2
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
 
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
 
Denys Serhiienko "ASGI in depth"
Denys Serhiienko "ASGI in depth"Denys Serhiienko "ASGI in depth"
Denys Serhiienko "ASGI in depth"
 
Debugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionDebugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 Version
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
 
Practical Celery
Practical CeleryPractical Celery
Practical Celery
 
And the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportAnd the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack Support
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12
 
Debugging: Rules & Tools
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & Tools
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Hidden Docs in Angular
Hidden Docs in AngularHidden Docs in Angular
Hidden Docs in Angular
 
Projeto-web-services-Spring-Boot-JPA.pdf
Projeto-web-services-Spring-Boot-JPA.pdfProjeto-web-services-Spring-Boot-JPA.pdf
Projeto-web-services-Spring-Boot-JPA.pdf
 
Heavy Web Optimization: Backend
Heavy Web Optimization: BackendHeavy Web Optimization: Backend
Heavy Web Optimization: Backend
 
Tasks: you gotta know how to run them
Tasks: you gotta know how to run themTasks: you gotta know how to run them
Tasks: you gotta know how to run them
 

More from it-people

«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Coit-people
 
«Scrapy internals» Александр Сибиряков, Scrapinghub
«Scrapy internals» Александр Сибиряков, Scrapinghub«Scrapy internals» Александр Сибиряков, Scrapinghub
«Scrapy internals» Александр Сибиряков, Scrapinghubit-people
 
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrainsit-people
 
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologiesit-people
 
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
«Ещё один Поиск Яндекса» Александр Кошелев, Яндексit-people
 
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...it-people
 
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalrit-people
 
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...it-people
 
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАН«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАНit-people
 
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банкit-people
 
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Coit-people
 
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНСit-people
 
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...it-people
 
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologiesit-people
 
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn Systemit-people
 
«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologies«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologiesit-people
 
«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндекс«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндексit-people
 
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...it-people
 
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognicianit-people
 
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...it-people
 

More from it-people (20)

«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
 
«Scrapy internals» Александр Сибиряков, Scrapinghub
«Scrapy internals» Александр Сибиряков, Scrapinghub«Scrapy internals» Александр Сибиряков, Scrapinghub
«Scrapy internals» Александр Сибиряков, Scrapinghub
 
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
 
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
 
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
 
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
 
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
 
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
 
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАН«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
 
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
 
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
 
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
 
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
 
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
 
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
 
«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologies«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologies
 
«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндекс«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндекс
 
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
 
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
 
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
 

Flask patterns

  • 1. Advanced Flask Patterns PyCon Russia 2013 — a presentation by Armin Ronacher @mitsuhiko
  • 2. -1 Who am I?
  • 3. That's me ✤ Armin Ronacher ✤ @mitsuhiko ✤ Creator of Flask/Werkzeug/Jinja2
  • 4. 0 Focus & Caveats
  • 5. Interrupt me ✤ Assumes some sense of Flask knowledge ✤ If too fast, interrupt me ✤ If not detailed enough, let me know
  • 6. 1 State Management
  • 7. Flask States ✤ Setup State ✤ Application Context Bound ✤ Request Context Bound
  • 8. Setup State >>> from flask import g >>> g.foo = 42 Traceback (most recent call last): File "<stdin>", line 1, in <module> RuntimeError: working outside of application context
  • 9. Application Bound >>> ctx = app.app_context() >>> ctx.push() >>> g.foo = 42 >>> g.foo 42 >>> from flask import request >>> request.args Traceback (most recent call last): File "<stdin>", line 1, in <module> RuntimeError: working outside of request context
  • 10. Request Bound >>> ctx = app.test_request_context() >>> ctx.push() >>> request.url 'http://localhost/' >>> g.foo = 42 >>> g.foo 42
  • 11. Lifetimes ✤ flask.current_app ⇝ application context ✤ flask.g ⇝ application context (as of 0.10) ✤ flask.request ⇝ request context ✤ flask.session ⇝ request context
  • 12. Quick Overview ✤ Application contexts are fast to create/destroy ✤ Pushing request context pushes new application context ✤ Flask 0.10 binds g to the application context ✤ Bind resources to the application context
  • 13. 2 Resource Management
  • 14. Basic Guide ✤ Create/Destroy Application Context == Task ✤ Bind resources task wise ✤ Resources: claimed database connections, caches
  • 15. Teardown Illustrated >>> from flask import Flask >>> app = Flask(__name__) >>> @app.teardown_appcontext ... def called_on_teardown(error=None): ... print 'Tearing down, error:', error ... >>> ctx = app.app_context() >>> ctx.push() >>> >>> ctx.pop() Tearing down, error: None >>> with app.app_context(): ... 1/0 ... Tearing down, error: integer division or modulo by zero Traceback (most recent call last): File "<stdin>", line 2, in <module> ZeroDivisionError: integer division or modulo by zero
  • 16. Resource Management def get_database_connection(): con = getattr(g, 'database_connection', None) if con is None: g.con = con = connection_pool.get_connection() return con @app.teardown_appcontext def return_database_connection(error=None): con = getattr(g, 'database_connection', None) if con is not None: connection_pool.release_connection(con)
  • 17. Responsive Resources @app.teardown_appcontext def return_database_connection(error=None): con = getattr(g, 'database_connection', None) if con is None: return if error is None: con.commit() else: con.rollback() connection_pool.release_connection(con)
  • 18. Per-Task Callbacks def after_commit(f): callbacks = getattr(g, 'on_commit_callbacks', None) if callbacks is None: g.on_commit_callbacks = callbacks = [] callbacks.append(f) return f
  • 19. Per-Task Callbacks @app.teardown_appcontext def return_database_connection(error=None): con = getattr(g, 'database_connection', None) if con is None: return if error is None: con.commit() callbacks = getattr(g, 'on_commit_callbacks', ()) for callback in callbacks: callback() else: con.rollback() connection_pool.release_connection(con)
  • 20. Per-Task Callbacks Example def purchase_product(product, user): user.purchased_products.append(product) @after_commit def send_success_mail(): body = render_template('mails/product_purchased.txt', user=user, product=product ) send_mail(user.email_address, 'Product Purchased', body)
  • 21. 3 Response Creation
  • 22. Response Object Passing ✤ One request object: read only ✤ Potentially many response objects, passed down a stack ✤ … can be implicitly created ✤ … can be replaced by other response objects ✤ there is no flask.response!
  • 23. Implicit Response Creation @app.route('/') def index(): return render_template('index.html')
  • 24. Explicit Creation from flask import make_response @app.route('/') def index(): body = render_template('index.html') response = make_response(body) response.headers['X-Powered-By'] = 'Not-PHP/1.0' return response
  • 25. Customized Creation from flask import Flask, jsonify class CustomFlask(Flask): def make_response(self, rv): if hasattr(rv, 'to_json'): return jsonify(rv.to_json()) return Flask.make_response(self, rv)
  • 26. Customized Creation Example class User(object): def __init__(self, id, username): self.id = id self.username = username def to_json(self): return { 'id': self.id, 'username': self.username } app = CustomFlask(__name__) @app.route('/') def index(): return User(42, 'john')
  • 27. 4 Server Sent Events
  • 28. Basic Overview ✤ Open Socket ✤ Sends "data: <data>rnrn" packets ✤ Good idea for gevent/eventlet, bad idea for kernel level concurrency
  • 29. Subscribing from redis import Redis from flask import Response, stream_with_context redis = Redis() @app.route('/streams/interesting') def stream(): def generate(): pubsub = redis.pubsub() pubsub.subscribe('interesting-channel') for event in pubsub.listen(): if event['type'] == 'message': yield 'data: %srnrn' % event['data'] return Response(stream_with_context(generate()), direct_passthrough=True, mimetype='text/event-stream')
  • 30. Publishing from flask import json, redirect, url_for @app.route('/create-something', methods=['POST']) def create_something(): create_that_thing() redis.publish('interesting-channel', json.dumps({ 'event': 'created', 'kind': 'something' })) return redirect(url_for('index'))
  • 31. Don't be Afraid of Proxying ✤ gunicorn/uwsgi blocking for main app ✤ gunicorn gevent for SSE ✤ nginx for unification
  • 32. 5 Worker Separation
  • 33. supervisor config [program:worker-blocking] command=gunicorn -w 4 yourapplication:app -b 0.0.0.0:8000 [program:worker-nonblocking] command=gunicorn -k gevent -w 4 yourapplication:app -b 0.0.0.0:8001
  • 34. nginx config server { listen 80; server_name example.com; location /streams { proxy_set_header Host $http_host; proxy_pass http://localhost:8001/streams; } location / { proxy_set_header Host $http_host; proxy_pass http://localhost:8000/; } }
  • 35. 6 Signing Stuff
  • 36. Basic Overview ✤ Use itsdangerous for signing information that roundtrips ✤ Saves you from storing information in a database ✤ Especially useful for small pieces of information that need to stay around for long (any form of token etc.)
  • 37. User Activation Example from flask import abort import itsdangerous serializer = itsdangerous .URLSafeSerializer(secret_key=app.config['SECRET_KEY']) ACTIVATION_SALT = 'x7fxfbxc2(;rxa8Ox16{' def get_activation_link(user): return url_for('activate', code=serializer.dumps(user.user_id, salt=ACTIVATION_SALT)) @app.route('/activate/<code>') def activate(code): try: user_id = serializer.loads(code, salt=ACTIVATION_SALT) except itsdangerous.BadSignature: abort(404) activate_the_user_with_id(user_id)
  • 38. 7 Customization
  • 39. Simple Cache Busting from hashlib import md5 import pkg_resources ASSET_REVISION = md5(str(pkg_resources.get_distribution( 'Package-Name').version)).hexdigest())[:14] @app.url_defaults def static_cache_buster(endpoint, values): if endpoint == 'static': values['_v'] = ASSET_REVISION
  • 40. Disable Parsing from flask import Flask, Request class SimpleRequest(Request): want_form_data_parsed = False data = None app = Flask(__name__) app.request_class = SimpleRequest
  • 41. 8 Secure Redirects
  • 42. Redirect Back from urlparse import urlparse, urljoin def is_safe_url(target): ref_url = urlparse(request.host_url) test_url = urlparse(urljoin(request.host_url, target)) return test_url.scheme in ('http', 'https') and ref_url.netloc == test_url.netloc def is_different_url(url): this_parts = urlparse(request.url) other_parts = urlparse(url) return this_parts[:4] != other_parts[:4] and url_decode(this_parts.query) != url_decode(other_parts.query) def redirect_back(fallback): next = request.args.get('next') or request.referrer if next and is_safe_url(next) and is_different_url(next): return redirect(next) return redirect(fallback)
  • 43. Q&A http://fireteam.net/ — Armin Ronacher — @mitsuhiko