Developing Large Web Applications Using a Micro Framework

58
Developing Large Web Applications Using a Micro Framework Osvaldo Matos-Junior

description

Flask is a micro-framework written in python for web application development. Is "micro" because it keeps your core simple. However, is very extensible and delegates the responsibility for the developer to choose the preferred technologies, e.g. database or template rendering system. Understand how Flask can be used to develop a simple application or large web portals

Transcript of Developing Large Web Applications Using a Micro Framework

Page 1: Developing Large Web Applications Using a Micro Framework

Developing Large Web Applications Using a

Micro FrameworkOsvaldo Matos-Junior

Page 2: Developing Large Web Applications Using a Micro Framework

once upon a time...

Page 3: Developing Large Web Applications Using a Micro Framework
Page 4: Developing Large Web Applications Using a Micro Framework
Page 5: Developing Large Web Applications Using a Micro Framework
Page 6: Developing Large Web Applications Using a Micro Framework

The story starts with an April's Fool's Joke...

Page 7: Developing Large Web Applications Using a Micro Framework
Page 8: Developing Large Web Applications Using a Micro Framework

How an April Fool's Joke became a Framework with Good Intentions

(PyCon 2011)

Page 9: Developing Large Web Applications Using a Micro Framework

The “micro” in microframework means Flask aims to keep the core simple but extensible. Flask won’t make

many decisions for you.(Armin Ronacher)

Why micro?

Page 10: Developing Large Web Applications Using a Micro Framework

What's in the Box?● built in development server and debugger● integrated routing system● client side sessions (secure cookies)● django-inspired templating language

Page 11: Developing Large Web Applications Using a Micro Framework

Some Numbers● 800 LOC Code● 1500 LOC Tests● 200 A4 Pages of Documentation● over 3900 followers and 550 forks on github

Page 12: Developing Large Web Applications Using a Micro Framework

a minimal application in Flask

Page 13: Developing Large Web Applications Using a Micro Framework

Flask is Funfrom flask import Flaskapp = Flask(__name__)

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

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

Page 14: Developing Large Web Applications Using a Micro Framework

Easy to Setup$ pip install Flask$ python hello.py * Running on http://localhost:5000/

Page 15: Developing Large Web Applications Using a Micro Framework

What it looks like

Page 16: Developing Large Web Applications Using a Micro Framework

debug mode

Page 17: Developing Large Web Applications Using a Micro Framework
Page 18: Developing Large Web Applications Using a Micro Framework

URL building

Page 19: Developing Large Web Applications Using a Micro Framework

from flask import Flask, url_forapp = Flask(__name__)

@app.route('/login')def login(): pass

@app.route('/user/<username>')def profile(username): pass

with app.test_request_context(): print url_for('login') print url_for('login', next='/') print url_for('profile', username='John Doe') print url_for('static', filename='css/style.css', _external=True)

/login/login?next=//user/John%20Doehttp://localhost/static/css/style.css

Page 20: Developing Large Web Applications Using a Micro Framework

rendering templates

Page 21: Developing Large Web Applications Using a Micro Framework

hello.py

from flask import Flask, render_templateapp = Flask(__name__)

@app.route('/', defaults={'name': 'Flask'})@app.route('/<name>')def index(name): return render_template('hello.html', name=name)

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

Page 22: Developing Large Web Applications Using a Micro Framework

templates/hello.html

<head> <title>Greetings</title></head><body> Hello {{ name }}!</body>

Page 23: Developing Large Web Applications Using a Micro Framework
Page 24: Developing Large Web Applications Using a Micro Framework

Jinja2 (Django like)<html><head><title>{{ title }}</title></head><body> <ul id="navigation"> {% for item in navigation %} <li><a href="{{ item.href }}" class="{{ 'first' if loop.first }} ">{{ item.caption }}</a></li> {% endfor %} </ul> <h1>{{ title|capitalize|truncate(120) }}</h1> {{ text }}{% include "footer.html" %}</body></html>

Page 25: Developing Large Web Applications Using a Micro Framework

Template Filters<h1> {{ title|capitalize|truncate(120) }}</h1>

Built in: capitalize, lower, length, trim, striptags, truncate, urlize ...

Customize: slugify, timesince ...

Page 26: Developing Large Web Applications Using a Micro Framework

Macrosheader

footer

content

ads 1

ads 2

related content

300x250

Results for: "query"

GOFLASK

Ttile for resultLong text description for the result. Long text description for the result.

Ttile for resultLong text description for the result. Long text description for the result.

Ttile for resultLong text description for the result. Long text description for the result.

Ttile for resultLong text description for the result. Long text description for the result.

Page 27: Developing Large Web Applications Using a Micro Framework

Macros{# ads.html #}{% macro google_adsense(id, width=120, height=120) -%}<script>google_ad_client = "pub-XXXX"; google_ad_slot = "{{id}}";google_ad_width = "{{width}}"; google_ad_height = "{{height}}";<script /><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js" ></script>

{%- endmacro %}

{# sidebar.html #}{% from 'ads.html' import ads_google %}<div>{{ google_adsense('arroba', 300, 250) }}</div><div>{{ google_adsense('ads1', 300, 100) }}</div>{% include "related_content.html" %}<div>{{ google_adsense('ads2', 300, 100) }}</div>

Page 28: Developing Large Web Applications Using a Micro Framework

Template Inheritance

header

footer

content 2 R

header 2

footer 2

content 3header

footer

content

Page 29: Developing Large Web Applications Using a Micro Framework

Base Template<html><head> <link rel="stylesheet" href="style.css" /> <title>{% block title %}{% endblock %} - My Webpage</title></head><body> <div id="content">{% block content %}{% endblock %}</div> <div id="footer"> {% block footer %} &copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>. {% endblock %} </div></body>

Page 30: Developing Large Web Applications Using a Micro Framework

Child Template{% extends "base.html" %}{% block title %}Index{% endblock %}

{% block content %} <h1>Index</h1> <p class="important"> Welcome on my awesome homepage. </p>{% endblock %}

Page 31: Developing Large Web Applications Using a Micro Framework

render_template('child.html')<html><head> <link rel="stylesheet" href="style.css" /> <title>Index - My Webpage</title></head><body> <div id="content"><h1>Index</h1> <p class="important"> Welcome on my awesome homepage.</p> </div> <div id="footer">&copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>.</div></body>

Page 32: Developing Large Web Applications Using a Micro Framework

more...

Page 33: Developing Large Web Applications Using a Micro Framework

Request and Sessionsfrom flask import Flask, session, redirect, url_for, escape, requestapp = Flask(__name__)app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

@app.route('/login', methods=['GET', 'POST'])def login(): if request.method == 'POST': session['username'] = request.form['username'] return redirect(url_for('index')) return ''' <form action="" method="post"> <p><input type=text name=username> <p><input type=submit value=Login> </form>'''

Page 34: Developing Large Web Applications Using a Micro Framework

Request and [email protected]('/')def index(): if 'username' in session: return 'Logged in as %s' % escape(session['username']) return 'You are not logged in'

@app.route('/logout')def logout(): # remove the username from the session if it's there session.pop('username', None) return redirect(url_for('index'))

Page 35: Developing Large Web Applications Using a Micro Framework

Redirects and Errorsfrom flask import abort, redirect, url_for

@app.route('/')def index(): return redirect(url_for('login'))

@app.route('/login')def login(): abort(401)

@app.errorhandler(404)def page_not_found(error): return render_template('page_not_found.html'), 404

Page 36: Developing Large Web Applications Using a Micro Framework

Snippetsimport sqlite3from flask import g

def connect_db(): return sqlite3.connect('/path/to/database.db')

@app.before_requestdef before_request(): g.db = connect_db()

@app.teardown_requestdef teardown_request(exception): g.db.close()

Page 37: Developing Large Web Applications Using a Micro Framework

many extensions

Page 38: Developing Large Web Applications Using a Micro Framework

Flask-BabelFlask-CouchDBFlask-MongoKit

Flask-LoginFlask-Mail

Flask-ScriptFlask-SQLAlchemy

Flask-TestingFlask-WTF

...

Page 39: Developing Large Web Applications Using a Micro Framework

Flask-SQLAlchemyfrom flask import Flaskfrom flaskext.sqlalchemy import SQLAlchemy

app = Flask(__name__)db = SQLAlchemy(app)class User(db.Model): name = db.Column(db.String(40), primary_key=True) email = db.Column(db.String(100))

@@app.route('/user/<name>')def show_user(name): user = User.query.filter_by(name=name).first_or_404() return render_template('user.html', user=user)

Page 40: Developing Large Web Applications Using a Micro Framework

Flask-Testingfrom flaskext.testing import TestCasefrom hello import app

class AppTest(TestCase): def create_app(self): return app

def test_index(self): response = self.client.get('/')

self.assert200(response) self.assertTemplateUsed('index.html') title = self.get_cotext_variable('title') self.assertEqual('My Page', title)

Page 41: Developing Large Web Applications Using a Micro Framework

larger applications

Page 42: Developing Large Web Applications Using a Micro Framework
Page 43: Developing Large Web Applications Using a Micro Framework

getting started

Page 44: Developing Large Web Applications Using a Micro Framework

jusbrasil/web/

templates/static/

js/css/

views/utils/main.pyconfig.py

tests/bootstrap.shmanage.pyrequires.txt

Folders and Packagesjusbrasil/

web/templates/

noticias/index.htmlview.html

jurisprudencia/views/

__init__.pynoticias.pyjurisprudencia.pydiarios.pylegislacao.py...

Page 45: Developing Large Web Applications Using a Micro Framework

def create_app(config=None, app_name=None, blueprints=None):

app_name = app_name or __name__ app = flask.Flask(app_name, static_folder=None) configure_app(app, config) configure_blueprints(app, blueprints) configure_error_handlers(app) configure_database(app) configure_context_processors(app) configure_template_filters(app) configure_before_request(app) configure_extensions(app) configure_views(app) configure_admin(app) return app

Create App

Page 46: Developing Large Web Applications Using a Micro Framework

Catching HTTP Errorsdef configure_error_handlers(app): @app.errorhandler(401) def unauthorized(error): flask.flash(u'Para acessar você precisa estar logado.') return flask.redirect(url_for('login', next=request.url,_external=True))

@app.errorhandler(404) def page_not_found(error):

return render("errors/page_not_found.html"), 404

@app.errorhandler(500) def server_error_page(error):

return render("errors/server_error.html"), 500

Page 47: Developing Large Web Applications Using a Micro Framework

Own Extensionsfrom jusbrasil.search import poolfrom thriftclient import ThriftClient

class SearchClient(ThriftClient):

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

def init_app(self, app): if not app.config['TESTING']: self.pool = pool.ConnectionPool(

server_list=app.config['SEARCH_SERVERS'],timeout=app.config['SEARCH_TIMEOUT'],pool_size=app.config['SEARCH_POOL_SIZE'])

self.app = app

Page 48: Developing Large Web Applications Using a Micro Framework

Logged Users

def get_current_user(): return getattr(flask.g, 'user', None)

def configure_before_request(app):

@app.before_request def load_current_user(): flask.g.user = None if 'user' in session: flask.g.user = load_user_session(session['user'])

Page 49: Developing Large Web Applications Using a Micro Framework

Shortcutsfrom jusbrasil.web import cache

@cache.memoize()def get_object_or_404(id, document_type):

# no valid id if id < 0: abort(404)

_object = client.getDocument(document_type, id)

# document not found if _object is None: abort(404) return _object

Page 50: Developing Large Web Applications Using a Micro Framework

modularize

Page 51: Developing Large Web Applications Using a Micro Framework

Blueprintsimport flaskfrom jusbrasil.web.utils.shortcuts import get_object_or_404

app = flask.Blueprint('jurisprudencia', __name__)

@app.route('/<int:id>/<slug>')def view(id, slug):

juris = get_object_or_404(id, 'jurisprudencia') template = 'jurisprudencia/view.html' return render(template, juris=juris)

Page 52: Developing Large Web Applications Using a Micro Framework

Templates{% block title %} {{ juris.title }} {% endblock %}

{% block content %}<div class="jurisprudencia"> <h1>{{ juris.titulo }}</h1>

<div class="ementa">{{ juris.ementa }}</div> <a href="{{ juris.inteiroTeor }}">Download Inteiro Teor</a> <div class="acordao"> <h2>Acórdão</h2> {{ juris.acordao }}</div></div>{% endblock %}

Page 53: Developing Large Web Applications Using a Micro Framework

finally...

Page 54: Developing Large Web Applications Using a Micro Framework

Flask is a microframework for Python based on Werkzeug, Jinja 2 and good intentions.

Page 55: Developing Large Web Applications Using a Micro Framework

scaling

Page 56: Developing Large Web Applications Using a Micro Framework
Page 57: Developing Large Web Applications Using a Micro Framework

Osvaldo [email protected]

Q&AQ&A

Page 58: Developing Large Web Applications Using a Micro Framework

Referenceshttp://denied.immersedcode.org/http://flask.pocoo.org/http://jinja.pocoo.org/http://werkzeug.pocoo.org/http://www.quora.com/Flaskhttps://github.com/mitsuhiko/flaskhttp://www.slideshare.net/mitsuhiko/flaskhttps://github.com/italomaia/flask-empty