Developing Flask Extensions

1,165 views

Published on

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

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,165
On SlideShare
0
From Embeds
0
Number of Embeds
41
Actions
Shares
0
Downloads
32
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Developing Flask Extensions

  1. 1. DEVELOPING FLASK EXTENSIONS Rachel Sanders @ PyTennessee 2014
  2. 2. Rachel Sanders    Engineer at LinkedIn & PyLadiesSF organizer Our internal stack: Python + Flask Team lead for a 30K LOC Flask app
  3. 3. 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
  4. 4. The really really quick intro to Flask Like 3 min tops, promise
  5. 5. from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello San Dimas High!" if __name__ == "__main__": app.run()
  6. 6. whaaaaaaa?    No database?? No forms? No admin interface?
  7. 7. “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
  8. 8. All these are extensions    database  SQLAlchemy + Flask-SQLAlchemy forms  WTForms + FlaskWTF admin  Flask-Admin
  9. 9. The really quick intro to extending Flask Like 5 min, promise
  10. 10. from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello San Dimas High!" if __name__ == "__main__": app.run()
  11. 11. from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello San Dimas High!" if __name__ == "__main__": app.run()
  12. 12. extending Flask = changing app
  13. 13. 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
  14. 14. Flask-FeatureFlags with the power to turn code on or off
  15. 15. from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello San Dimas High!”
  16. 16. 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!"
  17. 17. 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!"
  18. 18. 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!"
  19. 19. {% if 'pytennesse' is active_feature %} “Hi PyTennessee!” {% else %} “Hello San Dimas High!” {% endif %}
  20. 20. FEATURE FLAG SPEC  feature flags stored in config  Jinja template test called “active_feature”  Module function called “is_active”
  21. 21. bit.ly/giantwallofcode
  22. 22. class FeatureFlags(object):
  23. 23. class FeatureFlags(object): def __init__(self, app=None):
  24. 24. class FeatureFlags(object): def __init__(self, app=None): if app is not None: self.init_app(app) def init_app(self, app):
  25. 25. 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’, {})
  26. 26. 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
  27. 27. FEATURE FLAGS SPEC  feature flags stored in config  Jinja template test  is_active function
  28. 28. {% if 'pytennesse' is active_feature %} “Hi PyTennessee!” {% else %} “Hello San Dimas High!” {% endif %}
  29. 29. 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’, {}) 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
  30. 30. 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
  31. 31. FEATURE FLAGS SPEC  feature flags stored in config  Jinja template test  is_active function
  32. 32. 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!"
  33. 33. 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
  34. 34. from flask import current_app def is_active(feature): feature_flagger = current_app.extensions['FeatureFlags'] return feature_flagger.in_config(feature)
  35. 35. FEATURE FLAGS SPEC  feature flags stored in config  Jinja template test  is_active function
  36. 36. 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
  37. 37. Beyond the basics ok what now lady
  38. 38. Flask-DebugToolbar http://flask-debugtoolbar.readthedocs.org/
  39. 39. other great extensions    Flask-SeaSurf – request processing, cookies Flask-Admin – SQLAlchemy, blueprints, static files Flask-Classy – adds class-based views
  40. 40. thanks everybody!    @trustrachel github.com/trustrachel trustrachel.com

×