View
93
Download
0
Category
Preview:
Citation preview
__INIT__.PYfrom 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,
FLASK-SCRIPTCommands for running a development server, a customised
Python shell, etcpip 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 CONTEXTfrom 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.pyusage: 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
FLASK-SQLALCHEMY
Single wrapper for most of SQLAlchemyPreconfigured scope sessionSessions are tied to the page lifecycle
pip install flask-sqlalchemy
__INIT__.PYfrom 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.PYfrom flask.ext.script import Command
from flaskfilled import dbfrom 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()
MANAGE.PYfrom flask.ext.migrate import Migrate, MigrateCommand
migrate = Migrate(app, db)
manager.add_command('db', MigrateCommand)
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.py
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
FLASK-LOGIN
Simplifies logging users in and outSecures view functions with decoratorsProtects session cookies
pip install flask-login
FLASKFILLED/__INIT__.PYfrom 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 METHODSPROVIDED 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 authfrom 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_requireddef 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 register
MAIN/VIEWS.PYfrom 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/8d9327f04f_user.py
$ python manage.py db upgrade
INFO [alembic.migration] Running upgrade 586131216f6 -> 8d9327f04f, User
AUTH/FORMS.PYfrom flask.ext.wtf import Formfrom wtforms import StringField, PasswordField, SubmitFieldfrom 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 }}
__INIT__.PYfrom 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.connectdef 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.PYfrom flaskfilled.auth import admin_permission
@main.route('/settings', methods=['GET'])@admin_permission.require()def settings(): return render_template('main/settings.html')
__INIT__.PYfrom flask.ext.mail import Mailmail = Mail()
def create_app(config_name): mail.init_app(app)
__INIT__.PYfrom flask.ext.mail import Mailmail = Mail()
def create_app(config_name): mail.init_app(app)
MAIN/VIEWS.PYfrom 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 OUTTHERE?flask-securityflask-moment
https://github.com/humiaozuzu/awesome-flask
Recommended