writing your first web app using python and flask

71
flickr.com/photos/kevinomara/769

Upload: danielle-madeley

Post on 29-Nov-2014

4.620 views

Category:

Technology


3 download

DESCRIPTION

This tutorial will help you create your first webapp using Python and the Flask microframework. We will cover the following topics: * What is Flask and why would you use it * Rendering your first response * Handling forms and POST data * Using SQLAlchemy * Writing your first RESTful API * Holding open a connection to emit updates * Testing your app with py.test * Deploying to Redhat's Openshift platform Familiarity with Python is assumed. A passing familiarity with Javascript is recommended by not essential. https://github.com/danni/linux-conf-au-flask-tute http://mirror.linux.org.au/linux.conf.au/2014/Thursday/87-Writing_your_first_web_app_using_Python_and_Flask_-_Danielle_Madeley.mp4

TRANSCRIPT

Page 1: Writing your first web app using Python and Flask

Writing your firstweb app usingPython and Flask

Danielle Madeley, Infoxchange blogs.gnome.org/danni dannipenguin

flickr.com/photos/kevinomara/7695277030

Page 2: Writing your first web app using Python and Flask

If you haven't already...git clone

git://github.com/danni/linux-conf-au-flask-tute

Follow the README to set up yourenvironment

Page 3: Writing your first web app using Python and Flask

What is Flask and why would you use itRendering your first responseHandling forms and POST dataUsing SQLAlchemyWriting your first RESTful APIHolding open a connection to emit updatesTesting your app with py.testDeploying to Redhat's Openshift platform

Page 4: Writing your first web app using Python and Flask

import cgi Just kidding!

Page 5: Writing your first web app using Python and Flask

Just what is Flask?

flickr.com/photos/markstos/3579118891

Page 6: Writing your first web app using Python and Flask

Rendering yourfirst response

Page 7: Writing your first web app using Python and Flask

#!/usr/bin/env python

from flask import Flask

app = Flask(__name__)

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

Page 8: Writing your first web app using Python and Flask

#!/usr/bin/env python

from flask import Flask

app = Flask(__name__)

@app.route('/')def index(): """Homepage"""

return "Hello, linux.conf.au"

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

Page 9: Writing your first web app using Python and Flask

x â pythonÿenv�bin�activatex git checkout example÷ÎÏx pip install ÷r requirementsâtxtx python webapp�ÿÿinitÿÿâpy

Page 10: Writing your first web app using Python and Flask

from flask import redirect, render_template

@app.route('/a-redirect')def a_redirect(): """Redirect the user"""

return redirect(SOME_URL)

@app.route('/a-template')def a_template(): """Render a page using a Jinga2 template"""

return render_template('template.html')

Page 11: Writing your first web app using Python and Flask

By default: templates arelocated in the module'stemplates/ directory:

webapp/__init__.pytemplates/

template.html

Page 12: Writing your first web app using Python and Flask

x git checkout example÷ÎÐx pip install ÷r requirementsâtxtx python webapp�ÿÿinitÿÿâpy

Page 13: Writing your first web app using Python and Flask

handling querystrings

Page 14: Writing your first web app using Python and Flask

from flask import request

@app.route('/')def index(): """Return the name query argument"""

return request.args['name']

Page 15: Writing your first web app using Python and Flask

or doing itRESTfully

Page 16: Writing your first web app using Python and Flask

@app.route('/item/<int:pk>')def get_item(pk): """Return the item referred to by pk"""

# ...

Page 17: Writing your first web app using Python and Flask

?ou=Linux+Australia&ou=linux.conf.aurequestâargs�ëouë� �� ëLinux Australiaërequestâargsâgetlist�ëouë� �� �ëLinux Australiaëã ëlinuxâconfâauë� requestâargs�ënot presentë� raises KeyErrorrequestâargsâgetlist�ënot presentë� �� ��

Page 18: Writing your first web app using Python and Flask

handling forms andPOST data

Page 19: Writing your first web app using Python and Flask

from flask import request

@app.route('/')def index(): """Return the name POST value"""

return request.form['name']

Page 20: Writing your first web app using Python and Flask

or better still use aforms library

pip install Flask÷WTF

Page 21: Writing your first web app using Python and Flask

from flask import Flask, render_templatefrom flask.ext.wtf import Form

from wtforms import TextField

class RegoForm(Form): """A simple rego form"""

email = TextField('Email')

@app.route('/register', methods=('GET', 'POST'))def get_register(): """Handle the registration form"""

form = RegoForm()

if form.validate_on_submit(): return "Success"

return render_template('template.html', form=form)

if __name__ == '__main__': app.secret_key = 'THIS IS REALLY SECRET' app.run(debug=True)

Page 22: Writing your first web app using Python and Flask

from flask.ext.wtf import Form

from wtforms import TextField, validators

class RegoForm(Form): """A simple rego form"""

email = TextField('Email' validators=(validators.DataRequired(), validators.Email()))

Page 23: Writing your first web app using Python and Flask

<form method="post"> {{ form.hidden_tag() }} {# for CSRF.. important! #} {{ form.email.label }} {{ form.email }} {% if form.email.errors %} <ul> {% for error in form.email.errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} <input type="submit"></form>

Page 24: Writing your first web app using Python and Flask

SQL alchemy pip install Flask÷SQLAlchemy

Page 25: Writing your first web app using Python and Flask

from flask.ext.sqlalchemy import SQLAlchemy

db = SQLAlchemy(app)

class User(db.Model): """A user in my database"""

__tablename__ = 'users'

id = db.Column(db.Integer, primary_key=True)

# ...

Page 26: Writing your first web app using Python and Flask

if __name__ == "__main__": app.config['SQLALCHEMY_DATABASE_URI'] = \ 'postgresql://username:password@localhost/myapp' app.run(debug=True)

Page 27: Writing your first web app using Python and Flask

user = db.session.query(User)\ .filter(User.user_id == user_id)\ .one()

Page 28: Writing your first web app using Python and Flask

+ migrations(with Alembic)

pip install Flask÷Migrate

Page 29: Writing your first web app using Python and Flask

Detour:

Flask-Script

Page 30: Writing your first web app using Python and Flask

from flask import Flaskfrom flask.ext.script import Manager

app = Flask(__name__)manager = Manager(app)

if __name__ == '__main__': manager.run()

Page 31: Writing your first web app using Python and Flask

x python ÿÿinitÿÿâpyusageä ÿÿinitÿÿâpy �÷h� �shellãrunserver� âââ

positional argumentsä �shellãrunserver� shell Runs a Python shell inside Flask application contextâ runserver Runs the Flask development server iâeâ appârun��

optional argumentsä ÷hã ÷÷help show this help message and exit

x python ÿÿinitÿÿâpy runserver � Running on httpä��ÏÐÕâÎâÎâÏäÓÎÎÎ� � Restarting with reloader

Page 32: Writing your first web app using Python and Flask

from flask import Flaskfrom flask.ext.migrate import Migrate, MigrateCommandfrom flask.ext.script import Managerfrom flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)

manager = Manager(app)

db = SQLAlchemy(app)

migrate = Migrate(app, db)manager.add_command('db', MigrateCommand)

Page 33: Writing your first web app using Python and Flask

x python webapp�ÿÿinitÿÿâpy db initx git add migrations

Page 34: Writing your first web app using Python and Flask

x python webapp�ÿÿinitÿÿâpy db migratex git add migrations�versionsx python webapp�ÿÿinitÿÿâpy db upgrade

Page 35: Writing your first web app using Python and Flask

Tie it all together so far:

Models and Forms

Page 36: Writing your first web app using Python and Flask

from flask.ext.wtf import Form

from wtforms.ext.sqlalchemy.orm import model_form

class User(db.Model): """A user"""

__tablename__ = 'users'

id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(256), unique=True)

UserForm = model_form(User, base_class=Form)

Page 37: Writing your first web app using Python and Flask

from flask.ext.wtf import Form

from wtforms import validatorsfrom wtforms.ext.sqlalchemy.orm import model_form

UserForm = model_form(User, base_class=Form, field_args={ 'email': { 'validators': [validators.Email()], },})

Page 38: Writing your first web app using Python and Flask

from flask import Flask, request, render_template, redirect, url_for

@app.route('/register', methods=('GET', 'POST'))def register(): """Register a new user"""

obj = User() form = UserForm(request.form, obj)

if form.validate_on_submit(): form.populate_obj(obj) db.session.add(obj) db.session.commit()

return redirect(url_for('register'))

return render_template('template.html', form=form, users=User.query.all())

Page 39: Writing your first web app using Python and Flask

Emitting events(and other streams)

Page 40: Writing your first web app using Python and Flask

Detour:

Generators

Page 41: Writing your first web app using Python and Flask

def fibonacci(): """Generate an infinite Fibonacci sequence""" a = 0 b = 1

while True: yield b c = a + b a = b b = c

Page 42: Writing your first web app using Python and Flask

for i in fibonacci(): print i

# WARNING: will never end!

Page 43: Writing your first web app using Python and Flask

def fibonacci(n=10): """Generate an n elements of the Fibonacci sequence""" a = 0 b = 1

for i in xrange(n): yield b c = a + b a = b b = c

Page 44: Writing your first web app using Python and Flask

for i in fibonacci(): print iÏÏÐÑÓÖÏÑÐÏÑÒÓÓ

Page 45: Writing your first web app using Python and Flask

We can use agenerator to emitthe response!

Page 46: Writing your first web app using Python and Flask

from flask import Response, stream_with_context

@app.route('/events/stream')def get_events(): """Return a stream of events"""

@stream_with_context def generate(): """ A generator that returns a single JSON-encoded event, followed by an empty line. """

while True: yield get_event()

return Response(generate(), mimetype='text/event-stream')

Page 47: Writing your first web app using Python and Flask

x git checkout example÷ÎÓx pip install ÷r requirementsâtxtx python webapp�ÿÿinitÿÿâpy runserver ÷÷threaded

Page 48: Writing your first web app using Python and Flask

But wait!

Page 49: Writing your first web app using Python and Flask

Flask will gracefully finish requests.One request will never finish.

Page 50: Writing your first web app using Python and Flask

from flask.ext.script import (Manager, Server as ServerCommand)

class Server(ServerCommand): def handle(self, *args, **kwargs): app.running = True

super(Server, self).handle(*args, **kwargs)

print "Shutting down" app.running = False

manager.add_command('runserver', Server)

Page 51: Writing your first web app using Python and Flask

from Queue import Queue

queue = Queue()

@stream_with_contextdef generate(): """ Yield JSON-encoded events """

while app.running: try: item = queue.get(timeout=1)

yield format_messages([item]) queue.task_done() # eat the queue item except Empty: pass

Page 52: Writing your first web app using Python and Flask

the other sidewarning: javascript ahead

Page 53: Writing your first web app using Python and Flask

<title>Event Stream</title> <ul id="messages"> {% for message in get_flashed_messages() %} <li>{{ message }}</li> {% endfor %} </ul>

<script src="/static/bower/jquery.js" type="text/javascript"></script><script src="/static/bower/jquery.eventsource.js" type="text/javascript"></script

<script type="text/javascript">

</script>

$(document).ready(function() { $.eventsource({ label: 'connect', dataType: 'json', url: '/events/stream', message: function(data) { $.each(data, function() { $('<li>', { text: this }).appendTo('#messages'); }); } })});

Page 54: Writing your first web app using Python and Flask

x git checkout example÷ÎÔx pip install ÷r requirementsâtxtx bower install � NâBâ httpä��bowerâio�x python webapp�ÿÿinitÿÿâpy collectstatic

Page 55: Writing your first web app using Python and Flask

If you're into websockets you can look atgithub.com/kennethreitz/flask-sockets

Page 56: Writing your first web app using Python and Flask

Testing withpy.test

Page 57: Writing your first web app using Python and Flask

tests/conftest.pyimport pytest

from webapp import (app as flask_app, db as flask_db)

@pytest.fixture(scope='session')def db(): """Set up the database"""

flask_app.config['TESTING'] = True flask_app.config['SQLALCHEMY_DATABASE_URI'] = ...

flask_db.drop_all() flask_db.create_all()

return flask_db

@pytest.fixture(scope='session')def app(db): """Set up the Flask test client"""

return flask_app.test_client()

Page 58: Writing your first web app using Python and Flask

tests/test_views.py"""app and db are available in the test scope"""

def test_index(app): """Test I can get the index page"""

rv = app.get('/')

print rv.data

assert '<title>' in rv.data

Page 59: Writing your first web app using Python and Flask

x git checkout example÷ÎÕx pip install ÷r requirementsâtxtx pyâtest tests�

Page 60: Writing your first web app using Python and Flask

deploying toOpenShift

Page 61: Writing your first web app using Python and Flask

To deploy OpenShift runs your top-levelsetup.py

To serve requests OpenShift runswsgi.application.application

www.openshift.com/developers/python

Page 62: Writing your first web app using Python and Flask

setup.pyimport os

from setuptools import setup, find_packages

PROJECT_ROOT = os.environ.get('OPENSHIFT_REPO_DIR', os.path.dirname(os.path.abspath(__file__)))

with open(os.path.join(PROJECT_ROOT, 'requirements.txt')) as file_: requirements = [req.strip() for req in file_.xreadlines()]

setup(name='example', version='0.0', author='Danielle Madeley', author_email='[email protected]', url='https://github.com/danni/linux-conf-au-flask-tute', description='Example deploy to OpenShift', install_requires=requirements, )

Page 63: Writing your first web app using Python and Flask

wsgi/application.pyimport osimport sys

# add local codesys.path.append(os.path.join(os.environ['OPENSHIFT_REPO_DIR']))

# initialise virtual environmentvirtenv = os.environ['OPENSHIFT_HOMEDIR'] + 'python-2.7/virtenv/'os.environ['PYTHON_EGG_CACHE'] = os.path.join(virtenv, 'lib/python2.7/site-packages'

virtualenv = os.path.join(virtenv, 'bin/activate_this.py')

try: execfile(virtualenv, dict(__file__=virtualenv))except IOError: pass

# import and configure WSGI applicationfrom webapp import app as application

Page 64: Writing your first web app using Python and Flask

app = Flask(__name__)

app.secret_key = os.environ.get('OPENSHIFT_SECRET_TOKEN', 'THIS IS REALLY SECRET')app.config['SQLALCHEMY_DATABASE_URI'] = \ os.environ.get('OPENSHIFT_POSTGRESQL_DB_URL', 'sqlite:///../app.db')

try: app.static_folder = os.path.join(os.environ['OPENSHIFT_REPO_DIR'], 'wsgi'except KeyError: pass

Page 65: Writing your first web app using Python and Flask

(assuming you've set up Openshift)x rhc app create example python÷ÐâÕ ÷÷no÷gitx git remote add rhc sshä��âââ�example÷âââ�£�git�exampleâgit�

x rhc cartridge add ÷c postgresql÷×âÐ ÷a example

x git push rhc ÷÷force example÷ÎÖämaster

Page 66: Writing your first web app using Python and Flask

setup.pymanage.pywebapp

__init__.pymanager.pymodels.pyviews.pycollectstatic.pytemplates

events.htmltemplate.html

Page 67: Writing your first web app using Python and Flask

Going FurtherGetting Bigger

Page 68: Writing your first web app using Python and Flask

class based viewsfrom flask.views import MethodView

class UserAPI(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=UserAPI.as_view('users'))

Page 69: Writing your first web app using Python and Flask

blueprintsfrom flask import Blueprint, render_template

simple_page = Blueprint('simple_page', __name__, template_folder='templates')

@simple_page.route('/<page>')def show(page): return render_template('pages/%s.html' % page) </page>

Page 70: Writing your first web app using Python and Flask

blueprintsfrom flask import Flaskfrom module.simple_page import simple_page

app = Flask(__name__)app.register_blueprint(simple_page)

Page 71: Writing your first web app using Python and Flask

fin ;-)github.com/danni/linux-conf-au-flask-tute

blogs.gnome.org/danni dannipenguin

flickr.com/photos/mau3ry/3763640652