SlideShare a Scribd company logo
FILLING THE FLASK
Created by /Jason A Myers @jasonamyers
Filling the flask
Filling the flask
Filling the flask
Filling the flask
OUR EMPTY FLASK
I have two files setup: flaskfilled/__init__.py and config.py
__INIT__.PY
from flask import Flask
from config import config
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
return app
CONFIG.PY
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config:
SECRET_KEY = 'development key'
ADMINS = frozenset(['jason@jasonamyers.com', ])
class DevelopmentConfig(Config):
DEBUG = True
config = {
'development': DevelopmentConfig,
MANAGEMENT COMMANDS
FLASK-SCRIPT
Commands for running a development server, a customised
Python shell, etc
pip install flask-script
MANAGE.PY
#! /usr/bin/env python
import os
from flask.ext.script import Manager
from flaskfilled import create_app
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
manager = Manager(app)
if __name__ == '__main__':
manager.run()
SHELL WITH CONTEXT
from flask.ext.script import Shell
def make_shell_context():
return dict(app=app)
manager.add_command('shell', Shell(make_context=make_shell_context))
$ python manage.py
usage: manage.py [-?] {runserver,shell} ...
positional arguments:
{runserver,shell}
runserver Runs the Flask development server i.e. app.run()
shell Runs a Python shell inside Flask application context.
optional arguments:
-?, --help show this help message and exit
$ python manage.py shell
In [1]: app.config['DEBUG']
Out[1]: True
DATABASE ACCESS
FLASK-SQLALCHEMY
Single wrapper for most of SQLAlchemy
Preconfigured scope session
Sessions are tied to the page lifecycle
pip install flask-sqlalchemy
__INIT__.PY
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
db.init_app(app)
return app
CONFIG.PY
class DevelopmentConfig(Config):
DEBUG = True
SQLALCHEMY_DATABASE_URI = "sqlite:////tmp/dev.db"
FLASKFILLED/MODELS.PY
from flaskfilled import db
class Cookie(db.Model):
__tablename__ = 'cookies'
cookie_id = db.Column(db.Integer(), primary_key=True)
cookie_name = db.Column(db.String(50), index=True)
cookie_recipe_url = db.Column(db.String(255))
quantity = db.Column(db.Integer())
MANAGE.PY
from flask.ext.script import Command
from flaskfilled import db
from flaskfilled.models import Cookies
def make_shell_context():
return dict(app=app, db=db)
class DevDbInit(Command):
'''Creates database tables from sqlalchemy models'''
def __init__(self, db):
self.db = db
def run(self):
self.db.create_all()
$ python manage.py db_init
$ python manage.py shell
In [1]: db.metadata.tables
Out[1]: immutabledict({'cookies': Table('cookies', 'stuff')})
In [2]: from flaskfilled.models import Cookie
c = Cookie(cookie_name="Chocolate Chip",
cookie_recipe_url="http://zenofthecookie.com/chocolatechip.html"
quantity=2)
db.session.add(c)
db.session.commit()
MIGRATIONS
FLASK-MIGRATE
Ties Alembic into flask-script!
pip install flask-migrate
MANAGE.PY
from flask.ext.migrate import Migrate, MigrateCommand
migrate = Migrate(app, db)
manager.add_command('db', MigrateCommand)
INITIALIZING ALEMBIC
$ python manage.py db init
GENERATING A MIGRATION
$ python manage.py db migrate -m "initial migration"
INFO [alembic.migration] Context impl SQLiteImpl.
INFO [alembic.migration] Will assume non-transactional DDL.
Generating flask-filled/migrations/versions/586131216f6_initial_migration.p
RUNNING MIGRATIONS
$ python manage.py db upgrade
INFO [alembic.migration] Context impl SQLiteImpl.
INFO [alembic.migration] Will assume non-transactional DDL.
INFO [alembic.migration] Running upgrade -> 586131216f6, initial migration
USER AUTHENTICATION
FLASK-LOGIN
Simplifies logging users in and out
Secures view functions with decorators
Protects session cookies
pip install flask-login
FLASKFILLED/__INIT__.PY
from flask.ext.login import LoginManager
login_manager = LoginManager()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
db.init_app(app)
login_manager.setup_app(app)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/auth')
MODELS.PY
from werkzeug.security import generate_password_hash, check_password_hash
from flaskfilled import login_manager
class User(db.Model, UserMixin):
__tablename__ = 'users'
id = db.Column(db.Integer(), primary_key=True)
username = db.Column(db.String, primary_key=True)
password = db.Column(db.String)
authenticated = db.Column(db.Boolean, default=False)
USER MODEL REQUIRED METHODS
PROVIDED BY USERMIXIN
def is_active(self):
return True
def get_id(self):
return self.id
def is_authenticated(self):
return self.authenticated
def is_anonymous(self):
return False
USER MODEL PASSWORD HANDLING
@property
def password(self):
raise AttributeError('password is not a readable attribute')
@password.setter
def password(self, password):
self.password_hash = generate_password_hash(password)
def verify_password(self, password):
return check_password_hash(self.password_hash, password)
SETTING UP THE AUTH BLUEPRINT
AUTH/__INIT__.PY
from flask import Blueprint
auth = Blueprint('auth', __name__)
from . import views
AUTH/VIEWS.PY
from flask import render_template, redirect, request, url_for, flash
from flask.ext.login import login_user, logout_user, login_required
from . import auth
from flaskfilled.models import User
LOGIN
@auth.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form.get('username', '')
password = request.form.get('password', '')
user = User.query.filter_by(username=username).first()
if user is not None and user.verify_password(password):
login_user(user)
next = request.args.get('next')
return redirect(next or url_for('main.index'))
else:
flash('Wrong username or password.')
return render_template('auth/login.html')
LOGOUT
@auth.route('/logout')
@login_required
def logout():
logout_user()
flash('You have been logged out.')
return redirect(url_for('main.index'))
LOGIN TEMPLATE
{% extends "base.html" %}
{% block title %}Login{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Login</h1>
</div>
<div class="col-md-4">
<form action="">
Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<input type="submit">
</form>
<br>
<p>Forgot your password? <a href="{{ url_for('auth.password_reset_request
<p>New user? <a href="{{ url_for('auth.register') }}">Click here to regis
MAIN/VIEWS.PY
from flask import render_template
from . import main
@main.route('/', methods=['GET'])
def index():
return render_template('main/index.html')
INDEX TEMPLATE
{% extends "base.html" %}
{% block title %}The Index{% endblock %}
{% block page_content %}
{% if not current_user.is_authenticated() %}
<p><a href="{{ url_for('auth.login') }}">Click here to login</a>.</p
{% else %}
<p><a href="{{ url_for('auth.logout') }}">Click here to logout</a>.</
{% endif %}
{% endblock %}
CREATE USERS MIGRATION AND
APPLY IT
$ python manage.py db migrate -m "User"
Generating /Users/jasonamyers/dev/flask-filled/migrations/versions/8d9327f0
$ python manage.py db upgrade
INFO [alembic.migration] Running upgrade 586131216f6 -> 8d9327f04f, User
RUN SERVER
$ python manage.py runserver
Filling the flask
Filling the flask
Filling the flask
Filling the flask
Filling the flask
FORMS...
FLASK-WTF
Validation
CSRF protection
File Uploads
pip install flask-wtf
AUTH/FORMS.PY
from flask.ext.wtf import Form
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import Required, Length
class LoginForm(Form):
username = StringField('username', validators=[Required(),
Length(1, 64)])
password = PasswordField('Password', validators=[Required()])
submit = SubmitField('Log In')
AUTH/VIEWS.PY
@auth.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is not None and user.verify_password(form.password.data):
login_user(user)
next = request.args.get('next')
return redirect(next or url_for('main.index'))
else:
flash('Wrong username or password.')
return render_template('auth/login.html', form=form)
TEMPLATES/AUTH/LOGIN.HTML
{% block page_content %}
<div class="col-md-4">
<form action="" method="POST">
{{ form.csrf_token }}
{% if form.csrf_token.errors %}
<div class="warning">You have submitted an invalid CSRF token</
{% endif %}
{{form.username.label }}: {{ form.username }}
{% if form.username.errors %}
{% for error in form.username.errors %}
{{ error }}
{% endfor %}
{% endif %}<br>
{{form.password.label }}: {{ form.password }}
{% if form.password.errors %}
{% for error in form.password.errors %}
{{ error }}
AUTHORIZATION
FLASK-PRINCIPAL
pip install flask-principal
__INIT__.PY
from flask.ext.principal import Principal
principal = Principal()
def create_app(config_name):
principal.init_app(app)
MODELS.PY
roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer(),
db.ForeignKey('users.user_id')),
db.Column('role_id', db.Integer(),
db.ForeignKey('roles.id')))
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
description = db.Column(db.String(255))
MODELS.PY - USER CLASS
class User(db.Model, UserMixin):
roles = db.relationship('Role', secondary=roles_users,
primaryjoin=user_id == roles_users.c.user_id
backref='users')
MODELS.PY - IDENTITY LOADER
@identity_loaded.connect
def on_identity_loaded(sender, identity):
# Set the identity user object
identity.user = current_user
# Add the UserNeed to the identity
if hasattr(current_user, 'id'):
identity.provides.add(UserNeed(current_user.id))
# Assuming the User model has a list of roles, update the
# identity with the roles that the user provides
if hasattr(current_user, 'roles'):
for role in current_user.roles:
identity.provides.add(RoleNeed(role.name))
AUTH/VIEWS.PY
from flask import current_app
from flask.ext.principal import identity_changed, Identity
@auth.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is not None and user.verify_password(form.password.data):
login_user(user)
identity_changed.send(current_app._get_current_object(),
identity=Identity(user.user_id))
next = request.args.get('next')
return redirect(next or url_for('main.index'))
else:
AUTH/__INIT__.PY
from flask.ext.principal import Permission, RoleNeed
admin_permission = Permission(RoleNeed('admin'))
MAIN/VIEWS.PY
from flaskfilled.auth import admin_permission
@main.route('/settings', methods=['GET'])
@admin_permission.require()
def settings():
return render_template('main/settings.html')
Filling the flask
Filling the flask
SENDING MAIL
FLASK-MAIL
Works with Flask config
Simplies Message Construction
__INIT__.PY
from flask.ext.mail import Mail
mail = Mail()
def create_app(config_name):
mail.init_app(app)
__INIT__.PY
from flask.ext.mail import Mail
mail = Mail()
def create_app(config_name):
mail.init_app(app)
MAIN/VIEWS.PY
from flask_mail import Message
@main.route('/mailme', methods=['GET'])
def mail():
msg = Message('COOKIES!',
sender='from@example.com',
recipients=['to@example.com'])
msg.body = 'There all mine!'
msg.html = '<b>There all mine!</b>'
mail.send(msg)
WHAT OTHER THINGS ARE OUT
THERE?
flask-security
flask-moment
https://github.com/humiaozuzu/awesome-flask
QUESTIONS
Jason Myers / @jasonamyers / Essential SQLAlchemy 2nd Ed
O'Reilly

More Related Content

PDF
Flask - Backend com Python - Semcomp 18
PPTX
Flask – Python
PDF
Kyiv.py #17 Flask talk
PDF
Flask patterns
PDF
Flask Basics
PDF
Rest API using Flask & SqlAlchemy
PPTX
Flask restfulservices
PDF
BUILDING MODERN PYTHON WEB FRAMEWORKS USING FLASK WITH NEIL GREY
Flask - Backend com Python - Semcomp 18
Flask – Python
Kyiv.py #17 Flask talk
Flask patterns
Flask Basics
Rest API using Flask & SqlAlchemy
Flask restfulservices
BUILDING MODERN PYTHON WEB FRAMEWORKS USING FLASK WITH NEIL GREY

What's hot (20)

PDF
Flask RESTful Flask HTTPAuth
PDF
Flask SQLAlchemy
PDF
#30.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
PDF
Getting Started-with-Laravel
PDF
Flask Introduction - Python Meetup
KEY
CodeIgniter 3.0
KEY
Phpne august-2012-symfony-components-friends
PDF
Bootstrat REST APIs with Laravel 5
PPT
Dance for the puppet master: G6 Tech Talk
PDF
OSCON Google App Engine Codelab - July 2010
PPTX
New in php 7
KEY
Php Unit With Zend Framework Zendcon09
PDF
The Enterprise Wor/d/thy/Press
PPT
Learn flask in 90mins
PDF
A Little Backbone For Your App
PDF
WordPress REST API hacking
PDF
#31.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
PDF
Django
PDF
Phinx talk
PDF
Datagrids with Symfony 2, Backbone and Backgrid
Flask RESTful Flask HTTPAuth
Flask SQLAlchemy
#30.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
Getting Started-with-Laravel
Flask Introduction - Python Meetup
CodeIgniter 3.0
Phpne august-2012-symfony-components-friends
Bootstrat REST APIs with Laravel 5
Dance for the puppet master: G6 Tech Talk
OSCON Google App Engine Codelab - July 2010
New in php 7
Php Unit With Zend Framework Zendcon09
The Enterprise Wor/d/thy/Press
Learn flask in 90mins
A Little Backbone For Your App
WordPress REST API hacking
#31.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
Django
Phinx talk
Datagrids with Symfony 2, Backbone and Backgrid
Ad

Viewers also liked (20)

KEY
Quattro passi tra le nuvole (e non scordate il paracadute)
PPTX
Hands on django part 1
PDF
Intro python-object-protocol
KEY
Fuga dalla Comfort Zone
PDF
CoderDojo Romagna
PDF
Diabetes and Me: My Journey So Far
PDF
Python Static Analysis Tools
PDF
Introduction to SQLAlchemy and Alembic Migrations
PDF
Online / Offline
PDF
Coderfaire Data Networking for Developers
PPT
Flask - Python microframework
PDF
RESTful Web API and MongoDB go for a pic nic
PDF
Eve - REST API for Humans™
PDF
Introduction to SQLAlchemy ORM
PDF
We Are All Remote Workers
PDF
REST Web API with MongoDB
PDF
Impact of Restful Web Architecture on Performance and Scalability
PDF
Web develop in flask
PDF
Selenium testing
PDF
Django channels
Quattro passi tra le nuvole (e non scordate il paracadute)
Hands on django part 1
Intro python-object-protocol
Fuga dalla Comfort Zone
CoderDojo Romagna
Diabetes and Me: My Journey So Far
Python Static Analysis Tools
Introduction to SQLAlchemy and Alembic Migrations
Online / Offline
Coderfaire Data Networking for Developers
Flask - Python microframework
RESTful Web API and MongoDB go for a pic nic
Eve - REST API for Humans™
Introduction to SQLAlchemy ORM
We Are All Remote Workers
REST Web API with MongoDB
Impact of Restful Web Architecture on Performance and Scalability
Web develop in flask
Selenium testing
Django channels
Ad

Similar to Filling the flask (20)

PPTX
Flask Application ppt to understand the flask
PDF
Flask jwt authentication tutorial
PDF
Intro to Jinja2 Templates - San Francisco Flask Meetup
KEY
LvivPy - Flask in details
PDF
Jinja2 Templates - San Francisco Flask Meetup
PDF
Introduction to Flask Micro Framework
PDF
Flask Web Development 1st Edition Miguel Grinberg
PDF
Flask intro - ROSEdu web workshops
PDF
The Best (and Worst) of Django
PPTX
Build restful ap is with python and flask
PDF
Python Web Applications With Flask Handon Your Flask Skills2024 Jeffrey Leon ...
PDF
Enhance Your Flask Web Project With a Database Python Guide.pdf
PDF
Flask 소수전공 강의자료 - 3차시
PDF
How to Design a Great API (using flask) [ploneconf2017]
PDF
Docker and Django Meet For A Tango - London Meetup
PPTX
PDF
Using google appengine
PPTX
Django - sql alchemy - jquery
PPTX
Django crush course
PPTX
Django Schema Evolution for 5th sem.pptx
Flask Application ppt to understand the flask
Flask jwt authentication tutorial
Intro to Jinja2 Templates - San Francisco Flask Meetup
LvivPy - Flask in details
Jinja2 Templates - San Francisco Flask Meetup
Introduction to Flask Micro Framework
Flask Web Development 1st Edition Miguel Grinberg
Flask intro - ROSEdu web workshops
The Best (and Worst) of Django
Build restful ap is with python and flask
Python Web Applications With Flask Handon Your Flask Skills2024 Jeffrey Leon ...
Enhance Your Flask Web Project With a Database Python Guide.pdf
Flask 소수전공 강의자료 - 3차시
How to Design a Great API (using flask) [ploneconf2017]
Docker and Django Meet For A Tango - London Meetup
Using google appengine
Django - sql alchemy - jquery
Django crush course
Django Schema Evolution for 5th sem.pptx

Recently uploaded (20)

PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PPTX
Cloud computing and distributed systems.
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Empathic Computing: Creating Shared Understanding
PDF
Modernizing your data center with Dell and AMD
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Encapsulation theory and applications.pdf
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
cuic standard and advanced reporting.pdf
Digital-Transformation-Roadmap-for-Companies.pptx
Chapter 3 Spatial Domain Image Processing.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
20250228 LYD VKU AI Blended-Learning.pptx
Spectral efficient network and resource selection model in 5G networks
CIFDAQ's Market Insight: SEC Turns Pro Crypto
Per capita expenditure prediction using model stacking based on satellite ima...
Encapsulation_ Review paper, used for researhc scholars
Advanced methodologies resolving dimensionality complications for autism neur...
Cloud computing and distributed systems.
Review of recent advances in non-invasive hemoglobin estimation
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Empathic Computing: Creating Shared Understanding
Modernizing your data center with Dell and AMD
Building Integrated photovoltaic BIPV_UPV.pdf
MYSQL Presentation for SQL database connectivity
Encapsulation theory and applications.pdf
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
cuic standard and advanced reporting.pdf

Filling the flask

  • 1. FILLING THE FLASK Created by /Jason A Myers @jasonamyers
  • 6. OUR EMPTY FLASK I have two files setup: flaskfilled/__init__.py and config.py
  • 7. __INIT__.PY from flask import Flask from config import config def create_app(config_name): app = Flask(__name__) app.config.from_object(config[config_name]) return app
  • 8. CONFIG.PY import os basedir = os.path.abspath(os.path.dirname(__file__)) class Config: SECRET_KEY = 'development key' ADMINS = frozenset(['jason@jasonamyers.com', ]) class DevelopmentConfig(Config): DEBUG = True config = { 'development': DevelopmentConfig,
  • 10. FLASK-SCRIPT Commands for running a development server, a customised Python shell, etc pip install flask-script
  • 11. MANAGE.PY #! /usr/bin/env python import os from flask.ext.script import Manager from flaskfilled import create_app app = create_app(os.getenv('FLASK_CONFIG') or 'default') manager = Manager(app) if __name__ == '__main__': manager.run()
  • 12. SHELL WITH CONTEXT from flask.ext.script import Shell def make_shell_context(): return dict(app=app) manager.add_command('shell', Shell(make_context=make_shell_context))
  • 13. $ python manage.py usage: manage.py [-?] {runserver,shell} ... positional arguments: {runserver,shell} runserver Runs the Flask development server i.e. app.run() shell Runs a Python shell inside Flask application context. optional arguments: -?, --help show this help message and exit
  • 14. $ python manage.py shell In [1]: app.config['DEBUG'] Out[1]: True
  • 16. FLASK-SQLALCHEMY Single wrapper for most of SQLAlchemy Preconfigured scope session Sessions are tied to the page lifecycle pip install flask-sqlalchemy
  • 17. __INIT__.PY from flask.ext.sqlalchemy import SQLAlchemy db = SQLAlchemy() def create_app(config_name): app = Flask(__name__) app.config.from_object(config[config_name]) db.init_app(app) return app
  • 18. CONFIG.PY class DevelopmentConfig(Config): DEBUG = True SQLALCHEMY_DATABASE_URI = "sqlite:////tmp/dev.db"
  • 19. FLASKFILLED/MODELS.PY from flaskfilled import db class Cookie(db.Model): __tablename__ = 'cookies' cookie_id = db.Column(db.Integer(), primary_key=True) cookie_name = db.Column(db.String(50), index=True) cookie_recipe_url = db.Column(db.String(255)) quantity = db.Column(db.Integer())
  • 20. MANAGE.PY from flask.ext.script import Command from flaskfilled import db from flaskfilled.models import Cookies def make_shell_context(): return dict(app=app, db=db) class DevDbInit(Command): '''Creates database tables from sqlalchemy models''' def __init__(self, db): self.db = db def run(self): self.db.create_all()
  • 21. $ python manage.py db_init $ python manage.py shell In [1]: db.metadata.tables Out[1]: immutabledict({'cookies': Table('cookies', 'stuff')}) In [2]: from flaskfilled.models import Cookie
  • 22. c = Cookie(cookie_name="Chocolate Chip", cookie_recipe_url="http://zenofthecookie.com/chocolatechip.html" quantity=2) db.session.add(c) db.session.commit()
  • 24. FLASK-MIGRATE Ties Alembic into flask-script! pip install flask-migrate
  • 25. MANAGE.PY from flask.ext.migrate import Migrate, MigrateCommand migrate = Migrate(app, db) manager.add_command('db', MigrateCommand)
  • 26. INITIALIZING ALEMBIC $ python manage.py db init
  • 27. GENERATING A MIGRATION $ python manage.py db migrate -m "initial migration" INFO [alembic.migration] Context impl SQLiteImpl. INFO [alembic.migration] Will assume non-transactional DDL. Generating flask-filled/migrations/versions/586131216f6_initial_migration.p
  • 28. RUNNING MIGRATIONS $ python manage.py db upgrade INFO [alembic.migration] Context impl SQLiteImpl. INFO [alembic.migration] Will assume non-transactional DDL. INFO [alembic.migration] Running upgrade -> 586131216f6, initial migration
  • 30. FLASK-LOGIN Simplifies logging users in and out Secures view functions with decorators Protects session cookies pip install flask-login
  • 31. FLASKFILLED/__INIT__.PY from flask.ext.login import LoginManager login_manager = LoginManager() def create_app(config_name): app = Flask(__name__) app.config.from_object(config[config_name]) db.init_app(app) login_manager.setup_app(app) from .main import main as main_blueprint app.register_blueprint(main_blueprint) from .auth import auth as auth_blueprint app.register_blueprint(auth_blueprint, url_prefix='/auth')
  • 32. MODELS.PY from werkzeug.security import generate_password_hash, check_password_hash from flaskfilled import login_manager class User(db.Model, UserMixin): __tablename__ = 'users' id = db.Column(db.Integer(), primary_key=True) username = db.Column(db.String, primary_key=True) password = db.Column(db.String) authenticated = db.Column(db.Boolean, default=False)
  • 33. USER MODEL REQUIRED METHODS PROVIDED BY USERMIXIN def is_active(self): return True def get_id(self): return self.id def is_authenticated(self): return self.authenticated def is_anonymous(self): return False
  • 34. USER MODEL PASSWORD HANDLING @property def password(self): raise AttributeError('password is not a readable attribute') @password.setter def password(self, password): self.password_hash = generate_password_hash(password) def verify_password(self, password): return check_password_hash(self.password_hash, password)
  • 35. SETTING UP THE AUTH BLUEPRINT AUTH/__INIT__.PY from flask import Blueprint auth = Blueprint('auth', __name__) from . import views
  • 36. AUTH/VIEWS.PY from flask import render_template, redirect, request, url_for, flash from flask.ext.login import login_user, logout_user, login_required from . import auth from flaskfilled.models import User
  • 37. LOGIN @auth.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form.get('username', '') password = request.form.get('password', '') user = User.query.filter_by(username=username).first() if user is not None and user.verify_password(password): login_user(user) next = request.args.get('next') return redirect(next or url_for('main.index')) else: flash('Wrong username or password.') return render_template('auth/login.html')
  • 38. LOGOUT @auth.route('/logout') @login_required def logout(): logout_user() flash('You have been logged out.') return redirect(url_for('main.index'))
  • 39. LOGIN TEMPLATE {% extends "base.html" %} {% block title %}Login{% endblock %} {% block page_content %} <div class="page-header"> <h1>Login</h1> </div> <div class="col-md-4"> <form action=""> Username: <input type="text" name="username"><br> Password: <input type="password" name="password"><br> <input type="submit"> </form> <br> <p>Forgot your password? <a href="{{ url_for('auth.password_reset_request <p>New user? <a href="{{ url_for('auth.register') }}">Click here to regis
  • 40. MAIN/VIEWS.PY from flask import render_template from . import main @main.route('/', methods=['GET']) def index(): return render_template('main/index.html')
  • 41. INDEX TEMPLATE {% extends "base.html" %} {% block title %}The Index{% endblock %} {% block page_content %} {% if not current_user.is_authenticated() %} <p><a href="{{ url_for('auth.login') }}">Click here to login</a>.</p {% else %} <p><a href="{{ url_for('auth.logout') }}">Click here to logout</a>.</ {% endif %} {% endblock %}
  • 42. CREATE USERS MIGRATION AND APPLY IT $ python manage.py db migrate -m "User" Generating /Users/jasonamyers/dev/flask-filled/migrations/versions/8d9327f0 $ python manage.py db upgrade INFO [alembic.migration] Running upgrade 586131216f6 -> 8d9327f04f, User
  • 43. RUN SERVER $ python manage.py runserver
  • 51. AUTH/FORMS.PY from flask.ext.wtf import Form from wtforms import StringField, PasswordField, SubmitField from wtforms.validators import Required, Length class LoginForm(Form): username = StringField('username', validators=[Required(), Length(1, 64)]) password = PasswordField('Password', validators=[Required()]) submit = SubmitField('Log In')
  • 52. AUTH/VIEWS.PY @auth.route('/login', methods=['GET', 'POST']) def login(): form = LoginForm() if form.validate_on_submit(): user = User.query.filter_by(username=form.username.data).first() if user is not None and user.verify_password(form.password.data): login_user(user) next = request.args.get('next') return redirect(next or url_for('main.index')) else: flash('Wrong username or password.') return render_template('auth/login.html', form=form)
  • 53. TEMPLATES/AUTH/LOGIN.HTML {% block page_content %} <div class="col-md-4"> <form action="" method="POST"> {{ form.csrf_token }} {% if form.csrf_token.errors %} <div class="warning">You have submitted an invalid CSRF token</ {% endif %} {{form.username.label }}: {{ form.username }} {% if form.username.errors %} {% for error in form.username.errors %} {{ error }} {% endfor %} {% endif %}<br> {{form.password.label }}: {{ form.password }} {% if form.password.errors %} {% for error in form.password.errors %} {{ error }}
  • 56. __INIT__.PY from flask.ext.principal import Principal principal = Principal() def create_app(config_name): principal.init_app(app)
  • 57. MODELS.PY roles_users = db.Table('roles_users', db.Column('user_id', db.Integer(), db.ForeignKey('users.user_id')), db.Column('role_id', db.Integer(), db.ForeignKey('roles.id'))) class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(80), unique=True) description = db.Column(db.String(255))
  • 58. MODELS.PY - USER CLASS class User(db.Model, UserMixin): roles = db.relationship('Role', secondary=roles_users, primaryjoin=user_id == roles_users.c.user_id backref='users')
  • 59. MODELS.PY - IDENTITY LOADER @identity_loaded.connect def on_identity_loaded(sender, identity): # Set the identity user object identity.user = current_user # Add the UserNeed to the identity if hasattr(current_user, 'id'): identity.provides.add(UserNeed(current_user.id)) # Assuming the User model has a list of roles, update the # identity with the roles that the user provides if hasattr(current_user, 'roles'): for role in current_user.roles: identity.provides.add(RoleNeed(role.name))
  • 60. AUTH/VIEWS.PY from flask import current_app from flask.ext.principal import identity_changed, Identity @auth.route('/login', methods=['GET', 'POST']) def login(): form = LoginForm() if form.validate_on_submit(): user = User.query.filter_by(username=form.username.data).first() if user is not None and user.verify_password(form.password.data): login_user(user) identity_changed.send(current_app._get_current_object(), identity=Identity(user.user_id)) next = request.args.get('next') return redirect(next or url_for('main.index')) else:
  • 61. AUTH/__INIT__.PY from flask.ext.principal import Permission, RoleNeed admin_permission = Permission(RoleNeed('admin'))
  • 62. MAIN/VIEWS.PY from flaskfilled.auth import admin_permission @main.route('/settings', methods=['GET']) @admin_permission.require() def settings(): return render_template('main/settings.html')
  • 66. FLASK-MAIL Works with Flask config Simplies Message Construction
  • 67. __INIT__.PY from flask.ext.mail import Mail mail = Mail() def create_app(config_name): mail.init_app(app)
  • 68. __INIT__.PY from flask.ext.mail import Mail mail = Mail() def create_app(config_name): mail.init_app(app)
  • 69. MAIN/VIEWS.PY from flask_mail import Message @main.route('/mailme', methods=['GET']) def mail(): msg = Message('COOKIES!', sender='from@example.com', recipients=['to@example.com']) msg.body = 'There all mine!' msg.html = '<b>There all mine!</b>' mail.send(msg)
  • 70. WHAT OTHER THINGS ARE OUT THERE? flask-security flask-moment https://github.com/humiaozuzu/awesome-flask
  • 71. QUESTIONS Jason Myers / @jasonamyers / Essential SQLAlchemy 2nd Ed O'Reilly