Flask-OpenIDのサンプルアプリを Flask-SQLAlchemyとPyJadeを使って書きなおしてみた。
ディレクトリ構造
$ tree
.
├── app.py
└── templates
├── create_profile.jade
├── index.jade
├── layout.jade
└── login.jade
app.py
import os from flask import Flask, request, session, g, \ redirect, url_for, abort, render_template, flash, jsonify from flaskext.openid import OpenID from flaskext.sqlalchemy import SQLAlchemy DEBUG = True SECRET_KEY = 'openidsample' databese_file = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'oidsample.db') SQLALCHEMY_DATABASE_URI = 'sqlite:///%s' % databese_file app = Flask(__name__) app.config.from_object(__name__) app.jinja_env.add_extension('pyjade.ext.jinja.PyJadeExtension') db = SQLAlchemy(app) oid = OpenID(app, os.path.join(os.path.dirname(__file__), 'openid')) class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(60)) email = db.Column(db.String(200)) openid = db.Column(db.String(200)) def __init__(self, name, email, openid): self.name = name self.email = email self.openid = openid @app.before_request def lookup_current_user(): g.user = None if 'openid' in session: g.user = User.query.filter_by(openid=session['openid']).first() @app.route('/') def show_index(): return render_template('index.jade') @app.route('/login', methods=['GET', 'POST']) @oid.loginhandler def login(): if g.user is not None: return redirect(oid.get_next_url()) if request.method == 'POST': openid = request.form.get('openid') if openid: return oid.try_login(openid, ask_for=['email', 'fullname', 'nickname']) return render_template('login.jade', next=oid.get_next_url(), error=oid.fetch_error()) @oid.after_login def create_or_login(resp): session['openid'] = resp.identity_url user = User.query.filter_by(openid=resp.identity_url).first() if user is not None: flash(u'Successfully signed in') g.user = user return redirect(oid.get_next_url()) return redirect(url_for('create_profile', next=oid.get_next_url(), name=resp.fullname or resp.nickname, email=resp.email)) @app.route('/create-profile', methods=['GET', 'POST']) def create_profile(): if g.user is not None or 'openid' not in session: return redirect(url_for('index')) if request.method == 'POST': name = request.form['name'] email = request.form['email'] if not name: flash(u'Error: you have to provide a name') elif '@' not in email: flash(u'Error: you have to enter a valid email address') else: flash(u'Profile successfully created') db.session.add(User(name, email, session['openid'])) db.session.commit() return redirect(oid.get_next_url()) return render_template('create_profile.jade', next_url=oid.get_next_url()) @app.route('/logout') def logout(): session.pop('openid', None) flash(u'You were signed out') return redirect(oid.get_next_url()) if __name__ == '__main__': app.run()
layout.jade
bootstrap2をちょっと使いまわした。
!!! 5 html.no-js(lang='en') head title openid sample body .container block body
index.jade
extends "layout.jade" block body if g.user h1 you are logged in as {{ g.user.name }} p a(href="{{ url_for('logout') }}") Logout else h1 a(href="{{ url_for('login') }}") Login
login.jade
Flask-OpenIDのサンプルをhtml2jadeで変換した。
extends "layout.jade" block body h2 Sign in form(action='', method='post') | {% if error %} p.error strong Error: | {{ error }} | {% endif %} p | OpenID: input(type='text', name='openid', size='30') input(type='submit', value='Sign in') input(type='hidden', name='next', value='{{ next }}')
create_profile.jade
Flask-OpenIDのサンプルをhtml2jadeで変換した。
extends "layout.jade" block body h2 Create Profile p | Hey! This is the first time you signed in on this website. In | order to proceed we need a couple of more information from you: form(action='', method='post') dl dt | Name: dd input(type='text', name='name', size='30', value="{{ request.values.name }}") dt | E-Mail: dd input(type='text', name='email', size='30', value="{{ request.values.email }}") p input(type='submit', value='Create profile') input(type='hidden', name='next', value="{{ next }}") p If you don't want to proceed, you can a(href="{{ url_for('logout')}}") sign out again.
データベースを初期化するのに
>>> from app import db >>> db.create_all()
と叩く必要がある。