developing flask extensions

48
DEVELOPING FLASK EXTENSIONS Rachel Sanders @ PyTennessee 2014

Upload: rachel-sanders

Post on 15-Jun-2015

648 views

Category:

Technology


1 download

DESCRIPTION

Talk given at PyTennessee on 2014. Download the original for all the speaker notes.

TRANSCRIPT

Page 1: Developing Flask Extensions

DEVELOPING FLASK EXTENSIONS

Rachel Sanders @ PyTennessee 2014

Page 2: Developing Flask Extensions

Rachel Sanders Engineer at LinkedIn & PyLadiesSF

organizer Our internal stack: Python + Flask Team lead for a 30K LOC Flask app

Page 3: Developing Flask Extensions

What we talkin’ about The really really really quick intro to

Flask The really really quick intro to extending

Flask Flask-FeatureFlags: a case study Beyond the Basics Questions

Page 4: Developing Flask Extensions

Like 3 min tops, promise

The really really quick intro to Flask

Page 5: Developing Flask Extensions

from flask import Flask

app = Flask(__name__)

@app.route("/")

def hello():

return "Hello San Dimas High!"

if __name__ == "__main__":

app.run()

Page 6: Developing Flask Extensions

whaaaaaaa? No database?? No forms? No admin interface?

Page 7: Developing Flask Extensions

“The idea of Flask is to build a good foundation for all

applications. Everything else is up to you or

extensions.” -- Armin Ronacher, creator of

Flask

Page 8: Developing Flask Extensions

All these are extensions database SQLAlchemy + Flask-

SQLAlchemy forms WTForms + FlaskWTF admin Flask-Admin

Page 9: Developing Flask Extensions

Like 5 min, promise

The really quick intro to extending Flask

Page 10: Developing Flask Extensions

from flask import Flask

app = Flask(__name__)

@app.route("/")

def hello():

return "Hello San Dimas High!"

if __name__ == "__main__":

app.run()

Page 11: Developing Flask Extensions

from flask import Flask

app = Flask(__name__)

@app.route("/")

def hello():

return "Hello San Dimas High!"

if __name__ == "__main__":

app.run()

Page 12: Developing Flask Extensions

extending Flask

= changing app

Page 13: Developing Flask Extensions

You can change the app object by

Hooking into request lifecycle Adding more resources

Jinja filters, tests, global variables Routes, blueprints, static files

Middleware Monkeypatching

Page 14: Developing Flask Extensions
Page 15: Developing Flask Extensions
Page 16: Developing Flask Extensions

with the power to turn code on or off

Flask-FeatureFlags

Page 17: Developing Flask Extensions

from flask import Flask

app = Flask(__name__)

@app.route("/")

def hello():

return "Hello San Dimas High!”

Page 18: Developing Flask Extensions

from flask import Flask

import flask_featureflags as feature

app = Flask(__name__)

feature_flag = feature.FeatureFlag(app)

@app.route("/")

def hello():

return "Hello San Dimas High!"

Page 19: Developing Flask Extensions

from flask import Flask

import flask_featureflags as feature

app = Flask(__name__)

feature_flag = feature.FeatureFlag(app)

@app.route("/")

def hello():

if feature.is_active('pytennessee'):

return "Hello PyTennessee!"

else:

return "Hello San Dimas High!"

Page 20: Developing Flask Extensions

from flask import Flask

import flask_featureflags as feature

app = Flask(__name__)

feature_flag = feature.FeatureFlag(app)

app.config['FEATURE_FLAGS']['pytennessee'] = True

@app.route("/")

def hello():

if feature.is_active('pytennessee'):

return "Hello PyTennessee!"

else:

return "Hello San Dimas High!"

Page 21: Developing Flask Extensions

{% if 'pytennesse' is active_feature %} “Hi PyTennessee!”{% else %} “Hello San Dimas High!”{% endif %}

Page 22: Developing Flask Extensions

FEATURE FLAG SPEC

feature flags stored in config Jinja template test called “active_feature” Module function called “is_active”

Page 23: Developing Flask Extensions
Page 25: Developing Flask Extensions

class FeatureFlags(object):

Page 26: Developing Flask Extensions

class FeatureFlags(object):

def __init__(self, app=None):

Page 27: Developing Flask Extensions

class FeatureFlags(object):

def __init__(self, app=None): if app is not None: self.init_app(app)

def init_app(self, app):

Page 28: Developing Flask Extensions

class FeatureFlags(object):

def __init__(self, app=None): if app is not None: self.init_app(app)

def init_app(self, app):

app.config.setdefault('FEATURE_FLAGS’, {})

Page 29: Developing Flask Extensions

from flask import current_app

class FeatureFlags(object):

def __init__(self, app=None): if app is not None: self.init_app(app)

def init_app(self, app):

app.config.setdefault('FEATURE_FLAGS’, {})

def in_config(self, feature): try: return current_app.config['FEATURE_FLAGS'][feature] except (AttributeError, KeyError): return False

Page 30: Developing Flask Extensions

FEATURE FLAGS SPEC

feature flags stored in config Jinja template test is_active function

Page 31: Developing Flask Extensions

{% if 'pytennesse' is active_feature %} “Hi PyTennessee!”{% else %} “Hello San Dimas High!”{% endif %}

Page 32: Developing Flask Extensions

from flask import current_appclass FeatureFlags(object):

def __init__(self, app=None): if app is not None: self.init_app(app)

def init_app(self, app):

app.config.setdefault('FEATURE_FLAGS’, {})

app.add_template_test(self.in_config, name=’active_feature’)

def in_config(self, feature): try: return current_app.config['FEATURE_FLAGS'][feature] except (AttributeError, KeyError): return False

Page 33: Developing Flask Extensions
Page 34: Developing Flask Extensions
Page 35: Developing Flask Extensions
Page 36: Developing Flask Extensions

class FeatureFlags(object):

def __init__(self, app=None): if app is not None: self.init_app(app)

def init_app(self, app):

app.config.setdefault('FEATURE_FLAGS’, {})

if hasattr(app, "add_template_test"): app.add_template_test(self.in_config, name='active_feature') else: app.jinja_env.tests[’active_feature’] = self.in_config

Page 37: Developing Flask Extensions

FEATURE FLAGS SPEC

feature flags stored in config Jinja template test is_active function

Page 38: Developing Flask Extensions

from flask import Flask

import flask_featureflags as feature

app = Flask(__name__)

feature_flag = feature.FeatureFlag(app)

app.config['FEATURE_FLAGS']['pytennessee'] = True

@app.route("/")

def hello():

if feature.is_active('pytennessee'):

return "Hello PyTennessee!"

else:

return "Hello San Dimas High!"

Page 39: Developing Flask Extensions

class FeatureFlags(object):

def __init__(self, app=None): if app is not None: self.init_app(app)

def init_app(self, app):

app.config.setdefault('FEATURE_FLAGS’, {})

if hasattr(app, "add_template_test"): app.add_template_test(self.in_config, name='active_feature') else: app.jinja_env.tests[’active_feature’] = self.in_config

app.extensions['FeatureFlags'] = self

Page 40: Developing Flask Extensions

from flask import current_app

def is_active(feature): feature_flagger = current_app.extensions['FeatureFlags'] return feature_flagger.in_config(feature)

Page 41: Developing Flask Extensions

FEATURE FLAGS SPEC

feature flags stored in config Jinja template test is_active function

Page 42: Developing Flask Extensions

ok so what’d we learn? use init_app because app factories be sure to set config defaults calling Flask hooks 0.10+ is a trap how to get to our extension later

Page 43: Developing Flask Extensions

ok what now lady

Beyond the basics

Page 44: Developing Flask Extensions

http://flask-debugtoolbar.readthedocs.org/

Flask-DebugToolbar

Page 45: Developing Flask Extensions
Page 46: Developing Flask Extensions
Page 47: Developing Flask Extensions

other great extensions Flask-SeaSurf – request processing,

cookies Flask-Admin – SQLAlchemy, blueprints,

static files Flask-Classy – adds class-based views

Page 48: Developing Flask Extensions

thanks everybody! @trustrachel github.com/trustrachel trustrachel.com