Python on the Web
Put the Fun Back into Development
Armin Ronacher
@mitsuhiko [Link]
What is it?
fun
oriented object
dynamic
functional
.py
community focused
ped ly ty rong st
widely used
Who uses it?
And those are just the websites
Why?
Platforms? all*
*Win32, OS X, Linux, BSD, Symbian, Android
License? BSD-ish
Price? Free
Is it fast? fast enough
Is it reliable? NASA / banks use it
Why not $lang?
Parsing an Apache Logfile
with Python
The Logfile Format
.86 - - [20/Nov/[Link] +0100] "GET /[Link] HTTP/1.0" 200 25965 3.147 - - [20/Nov/[Link] +0100] "GET /[Link] HTTP/1.1" 304 153 3.35 - - [20/Nov/[Link] +0100] "GET /2008/1/23/no HTTP/1.0" 404 4 6.211 - - [20/Nov/[Link] +0100] "GET /[Link]?_qt=data HTTP/1.1
with open('/var/log/apache2/[Link]') as f: for line in f: ...
import re
with open('/var/log/apache2/[Link]') as f: for line in f: match = [Link](r' "\w+ (.*?) HTTP/', line) if match is None: continue print [Link](1).split('?')[0]
import re from collections import defaultdict counts = defaultdict(int) with open('/var/log/apache2/[Link]') as f: for line in f: match = [Link](r' "\w+ (.*?) HTTP/', line) if match is None: continue counts[[Link](1).split('?')[0]] += 1
import re from collections import defaultdict counts = defaultdict(int) with open('/var/log/apache2/[Link]') as f: for line in f: match = [Link](r' "\w+ (.*?) HTTP/', line) if match is None: continue counts[[Link](1).split('?')[0]] += 1 for url, count in [Link](): print '%s (%d times)' % (url, count)
import re from collections import defaultdict from heapq import nlargest counts = defaultdict(int) with open('/var/log/apache2/[Link]') as f: for line in f: match = [Link](r' "\w+ (.*?) HTTP/', line) if match is None: continue counts[[Link](1).split('?')[0]] += 1 most_common = nlargest(5, [Link](), key=lambda x: x[1]) for url, count in most_common: print '%s (%d times)' % (url, count)
import re from collections import defaultdict from heapq import nlargest counts = defaultdict(int) with open('/var/log/apache2/[Link]') as f: for line in f: match = [Link](r' "\w+ (.*?) HTTP/', line) if match is None: continue counts[[Link](1).split('?')[0]] += 1 most_common = nlargest(5, [Link](), key=lambda x: x[1]) for url, count in most_common: print '%s (%d times)' % (url, count)
Parsing an Apache Logle
with Java
import import import import import import
[Link]; [Link]; [Link]; [Link]; [Link]; [Link];
class LogParser { public static void main(String[] args) { try { String filename = "/var/log/apache2/[Link]"; FileInputStream fstream = new FileInputStream(filename); DataInputStream in = new DataInputStream(fstream); BufferedReader br = new BufferedReader(new InputStreamReader(in)); Map<String, Integer> counts = new HashMap<String, Integer>(); try { Pattern pattern = [Link](" \"\\w+ (.*?) HTTP/"); String line; while ((line = [Link]()) != null) { Matcher m = [Link](line); if (![Link]()) continue; String url = [Link](0).split("\\?")[0]; if ([Link](url)) [Link](url, [Link](url) + 1); else [Link](url, 1); } } finally { [Link](); } [Link]<String, Integer> items[] = [Link]().toArray(); [Link](new Comparator() { int compareTo([Link]<String, Integer> a, [Link]<String, Integer> b) { return [Link]().compareTo([Link]()); } }); for (int i = 0; i < [Link](5, [Link]); i++) { [Link]<String, Integer> item = items[i]; [Link]([Link]() + " (" + [Link]() + " times)"); } } catch (Exception e) { [Link](); } } }
Productivity++
To The Web
The Frameworks
Django Flask Pyramid Zope/Plone
The Stack
CSS
JavaScript
HTML
Browser
HTTP
Your App
Web Server
Python
WSGI
Framework
Y U NO SIMPLE?
Flask
[Link]
Step 0 Install virtualenv
$ sudo apt-get install python-virtualenv $ sudo easy_install virtualenv For windows: [Link]
Step 1 Create Environment
$ virtualenv my-app $ . my-app/bin/activate > my-app\Scripts\[Link]
Step 2 Install Flask
$ pip install Flask
Step 3 Hello World
from flask import Flask app = Flask(__name__) @[Link]('/') def index(): return 'Hello World!' if __name__ == '__main__': [Link]()
Step 4 Run!
$ python [Link] * Running on [Link]
What we like:
Develop locally Isolated environments Persistent execution Automatic code reloading Kick-ass debugging Logic / UI separation
If it crashes
Pastebin
Step 0 Overview
General Purpose Pastebin Users can sign in with Facebook Authenticated users can delete their entries Authenticated users can list their entries Flask, Flask-OAuth, Flask-SQLAlchemy
Step 0 Overview
/pastebin /static /[Link] /templates /[Link] /new_paste.html /delete_paste.html /my_pastes.html /[Link] Project Folder Static Files Templates
The Application
Step 1 Install Extensions
$ pip install Flask-OAuth Flask-SQLAlchemy
Step 2 Imports
from datetime import datetime from flask import Flask, request, url_for, redirect, g, session, \ abort, render_template from [Link] import SQLAlchemy from [Link] import OAuth
Step 2 Imports
from datetime import datetime from flask import Flask, request, url_for, redirect, g, session, \ abort, render_template from [Link] import SQLAlchemy from [Link] import OAuth
Step 2 Imports
from datetime import datetime from flask import Flask, request, url_for, redirect, g, session, \ abort, render_template from [Link] import SQLAlchemy from [Link] import OAuth
Step 2 Imports
from datetime import datetime from flask import Flask, request, url_for, redirect, g, session, \ abort, render_template from [Link] import SQLAlchemy from [Link] import OAuth
Step 3 Setup
app = Flask(__name__) [Link]( SQLALCHEMY_DATABASE_URI='sqlite:///[Link]', SECRET_KEY='development-key' ) db = SQLAlchemy(app) oauth = OAuth() facebook = oauth.remote_app('facebook', base_url='[Link] request_token_url=None, access_token_url='/oauth/access_token', authorize_url='[Link] consumer_key='<consumer key here>', consumer_secret='<consumer secret here>', request_token_params={'scope': 'email'} )
Step 3 Setup
app = Flask(__name__) [Link]( SQLALCHEMY_DATABASE_URI='sqlite:///[Link]', SECRET_KEY='development-key' ) db = SQLAlchemy(app) oauth = OAuth() facebook = oauth.remote_app('facebook', base_url='[Link] request_token_url=None, access_token_url='/oauth/access_token', authorize_url='[Link] consumer_key='<consumer key here>', consumer_secret='<consumer secret here>', request_token_params={'scope': 'email'} )
Step 3 Setup
app = Flask(__name__) [Link]( SQLALCHEMY_DATABASE_URI='sqlite:///[Link]', SECRET_KEY='development-key' ) db = SQLAlchemy(app) oauth = OAuth() facebook = oauth.remote_app('facebook', base_url='[Link] request_token_url=None, access_token_url='/oauth/access_token', authorize_url='[Link] consumer_key='<consumer key here>', consumer_secret='<consumer secret here>', request_token_params={'scope': 'email'} )
Step 3 Setup
app = Flask(__name__) [Link]( SQLALCHEMY_DATABASE_URI='sqlite:///[Link]', SECRET_KEY='development-key' ) db = SQLAlchemy(app) oauth = OAuth() facebook = oauth.remote_app('facebook', base_url='[Link] request_token_url=None, access_token_url='/oauth/access_token', authorize_url='[Link] consumer_key='<consumer key here>', consumer_secret='<consumer secret here>', request_token_params={'scope': 'email'} )
Step 3 Setup
app = Flask(__name__) [Link]( SQLALCHEMY_DATABASE_URI='sqlite:///[Link]', SECRET_KEY='development-key' ) db = SQLAlchemy(app) oauth = OAuth() facebook = oauth.remote_app('facebook', base_url='[Link] request_token_url=None, access_token_url='/oauth/access_token', authorize_url='[Link] consumer_key='<consumer key here>', consumer_secret='<consumer secret here>', request_token_params={'scope': 'email'} )
Step 4 Database Schema
class Paste([Link]): id = [Link]([Link], primary_key=True) code = [Link]([Link]) pub_date = [Link]([Link]) user_id = [Link]([Link], [Link]('[Link]')) def __init__(self, user, code): [Link] = user [Link] = code self.pub_date = [Link]() class User([Link]): id = [Link]([Link], primary_key=True) display_name = [Link]([Link](120)) fb_id = [Link]([Link](30), unique=True) pastes = [Link](Paste, lazy='dynamic', backref='user')
Step 4 Database Schema
class Paste([Link]): id = [Link]([Link], primary_key=True) code = [Link]([Link]) pub_date = [Link]([Link]) user_id = [Link]([Link], [Link]('[Link]')) def __init__(self, user, code): [Link] = user [Link] = code self.pub_date = [Link]() class User([Link]): id = [Link]([Link], primary_key=True) display_name = [Link]([Link](120)) fb_id = [Link]([Link](30), unique=True) pastes = [Link](Paste, lazy='dynamic', backref='user')
Step 4 Database Schema
class Paste([Link]): id = [Link]([Link], primary_key=True) code = [Link]([Link]) pub_date = [Link]([Link]) user_id = [Link]([Link], [Link]('[Link]')) def __init__(self, user, code): [Link] = user [Link] = code self.pub_date = [Link]() class User([Link]): id = [Link]([Link], primary_key=True) display_name = [Link]([Link](120)) fb_id = [Link]([Link](30), unique=True) pastes = [Link](Paste, lazy='dynamic', backref='user')
Step 4 Database Schema
class Paste([Link]): id = [Link]([Link], primary_key=True) code = [Link]([Link]) pub_date = [Link]([Link]) user_id = [Link]([Link], [Link]('[Link]')) def __init__(self, user, code): [Link] = user [Link] = code self.pub_date = [Link]() class User([Link]): id = [Link]([Link], primary_key=True) display_name = [Link]([Link](120)) fb_id = [Link]([Link](30), unique=True) pastes = [Link](Paste, lazy='dynamic', backref='user')
Step 4 Database Schema
class Paste([Link]): id = [Link]([Link], primary_key=True) code = [Link]([Link]) pub_date = [Link]([Link]) user_id = [Link]([Link], [Link]('[Link]')) def __init__(self, user, code): [Link] = user [Link] = code self.pub_date = [Link]() class User([Link]): id = [Link]([Link], primary_key=True) display_name = [Link]([Link](120)) fb_id = [Link]([Link](30), unique=True) pastes = [Link](Paste, lazy='dynamic', backref='user')
Step 4 Database Schema
class Paste([Link]): id = [Link]([Link], primary_key=True) code = [Link]([Link]) pub_date = [Link]([Link]) user_id = [Link]([Link], [Link]('[Link]')) def __init__(self, user, code): [Link] = user [Link] = code self.pub_date = [Link]() class User([Link]): id = [Link]([Link], primary_key=True) display_name = [Link]([Link](120)) fb_id = [Link]([Link](30), unique=True) pastes = [Link](Paste, lazy='dynamic', backref='user')
Step 4 Database Schema
class Paste([Link]): id = [Link]([Link], primary_key=True) code = [Link]([Link]) pub_date = [Link]([Link]) user_id = [Link]([Link], [Link]('[Link]')) def __init__(self, user, code): [Link] = user [Link] = code self.pub_date = [Link]() class User([Link]): id = [Link]([Link], primary_key=True) display_name = [Link]([Link](120)) fb_id = [Link]([Link](30), unique=True) pastes = [Link](Paste, lazy='dynamic', backref='user')
Step 5 Authentication
@app.before_request def check_user_status(): [Link] = None if 'user_id' in session: [Link] = [Link](session['user_id']) @[Link] def get_facebook_oauth_token(): return [Link]('fb_access_token')
Step 5 Authentication
@app.before_request def check_user_status(): [Link] = None if 'user_id' in session: [Link] = [Link](session['user_id']) @[Link] def get_facebook_oauth_token(): return [Link]('fb_access_token')
Step 5 Authentication
@app.before_request def check_user_status(): [Link] = None if 'user_id' in session: [Link] = [Link](session['user_id']) @[Link] def get_facebook_oauth_token(): return [Link]('fb_access_token')
Step 5 Authentication
@[Link]('/login') def login(): return [Link](callback=url_for('facebook_authorized', next=[Link]('next') or [Link] or None, _external=True)) @[Link]('/logout') def logout(): [Link]() return redirect(url_for('new_paste'))
Step 5 Authentication
@[Link]('/login') def login(): return [Link](callback=url_for('facebook_authorized', next=[Link]('next') or [Link] or None, _external=True)) @[Link]('/logout') def logout(): [Link]() return redirect(url_for('new_paste'))
Step 5 Authentication
@[Link]('/login') def login(): return [Link](callback=url_for('facebook_authorized', next=[Link]('next') or [Link] or None, _external=True)) @[Link]('/logout') def logout(): [Link]() return redirect(url_for('new_paste'))
Step 5 Authentication
@[Link]('/login') def login(): return [Link](callback=url_for('facebook_authorized', next=[Link]('next') or [Link] or None, _external=True)) @[Link]('/logout') def logout(): [Link]() return redirect(url_for('new_paste'))
Step 5 Authentication
@[Link]('/login/authorized') @facebook.authorized_handler def facebook_authorized(resp): next_url = [Link]('next') or url_for('new_paste') if resp is None: return redirect(next_url) session['fb_access_token'] = (resp['access_token'], '') me = [Link]('/me') user = [Link].filter_by(fb_id=[Link]['id']).first() if user is None: user = User() user.fb_id = [Link]['id'] [Link](user) user.display_name = [Link]['name'] [Link]() session['user_id'] = [Link] return redirect(next_url)
Step 5 Authentication
@[Link]('/login/authorized') @facebook.authorized_handler def facebook_authorized(resp): next_url = [Link]('next') or url_for('new_paste') if resp is None: return redirect(next_url) session['fb_access_token'] = (resp['access_token'], '') me = [Link]('/me') user = [Link].filter_by(fb_id=[Link]['id']).first() if user is None: user = User() user.fb_id = [Link]['id'] [Link](user) user.display_name = [Link]['name'] [Link]() session['user_id'] = [Link] return redirect(next_url)
Step 5 Authentication
@[Link]('/login/authorized') @facebook.authorized_handler def facebook_authorized(resp): next_url = [Link]('next') or url_for('new_paste') if resp is None: return redirect(next_url) session['fb_access_token'] = (resp['access_token'], '') me = [Link]('/me') user = [Link].filter_by(fb_id=[Link]['id']).first() if user is None: user = User() user.fb_id = [Link]['id'] [Link](user) user.display_name = [Link]['name'] [Link]() session['user_id'] = [Link] return redirect(next_url)
Step 5 Authentication
@[Link]('/login/authorized') @facebook.authorized_handler def facebook_authorized(resp): next_url = [Link]('next') or url_for('new_paste') if resp is None: return redirect(next_url) session['fb_access_token'] = (resp['access_token'], '') me = [Link]('/me') user = [Link].filter_by(fb_id=[Link]['id']).first() if user is None: user = User() user.fb_id = [Link]['id'] [Link](user) user.display_name = [Link]['name'] [Link]() session['user_id'] = [Link] return redirect(next_url)
Step 5 Authentication
@[Link]('/login/authorized') @facebook.authorized_handler def facebook_authorized(resp): next_url = [Link]('next') or url_for('new_paste') if resp is None: return redirect(next_url) session['fb_access_token'] = (resp['access_token'], '') me = [Link]('/me') user = [Link].filter_by(fb_id=[Link]['id']).first() if user is None: user = User() user.fb_id = [Link]['id'] [Link](user) user.display_name = [Link]['name'] [Link]() session['user_id'] = [Link] return redirect(next_url)
Step 5 Authentication
@[Link]('/login/authorized') @facebook.authorized_handler def facebook_authorized(resp): next_url = [Link]('next') or url_for('new_paste') if resp is None: return redirect(next_url) session['fb_access_token'] = (resp['access_token'], '') me = [Link]('/me') user = [Link].filter_by(fb_id=[Link]['id']).first() if user is None: user = User() user.fb_id = [Link]['id'] [Link](user) user.display_name = [Link]['name'] [Link]() session['user_id'] = [Link] return redirect(next_url)
Step 5 Authentication
@[Link]('/login/authorized') @facebook.authorized_handler def facebook_authorized(resp): next_url = [Link]('next') or url_for('new_paste') if resp is None: return redirect(next_url) session['fb_access_token'] = (resp['access_token'], '') me = [Link]('/me') user = [Link].filter_by(fb_id=[Link]['id']).first() if user is None: user = User() user.fb_id = [Link]['id'] [Link](user) user.display_name = [Link]['name'] [Link]() session['user_id'] = [Link] return redirect(next_url)
Step 5 Authentication
@[Link]('/login/authorized') @facebook.authorized_handler def facebook_authorized(resp): next_url = [Link]('next') or url_for('new_paste') if resp is None: return redirect(next_url) session['fb_access_token'] = (resp['access_token'], '') me = [Link]('/me') user = [Link].filter_by(fb_id=[Link]['id']).first() if user is None: user = User() user.fb_id = [Link]['id'] [Link](user) user.display_name = [Link]['name'] [Link]() session['user_id'] = [Link] return redirect(next_url)
Step 5 Authentication
@[Link]('/login/authorized') @facebook.authorized_handler def facebook_authorized(resp): next_url = [Link]('next') or url_for('new_paste') if resp is None: return redirect(next_url) session['fb_access_token'] = (resp['access_token'], '') me = [Link]('/me') user = [Link].filter_by(fb_id=[Link]['id']).first() if user is None: user = User() user.fb_id = [Link]['id'] [Link](user) user.display_name = [Link]['name'] [Link]() session['user_id'] = [Link] return redirect(next_url)
Step 5 Authentication
@[Link]('/login/authorized') @facebook.authorized_handler def facebook_authorized(resp): next_url = [Link]('next') or url_for('new_paste') if resp is None: return redirect(next_url) session['fb_access_token'] = (resp['access_token'], '') me = [Link]('/me') user = [Link].filter_by(fb_id=[Link]['id']).first() if user is None: user = User() user.fb_id = [Link]['id'] [Link](user) user.display_name = [Link]['name'] [Link]() session['user_id'] = [Link] return redirect(next_url)
Step 6 View Functions
@[Link]('/', methods=['GET', 'POST']) def new_paste(): if [Link] == 'POST' and [Link]['code']: paste = Paste([Link], [Link]['code']) [Link](paste) [Link]() return redirect(url_for('show_paste', paste_id=[Link])) return render_template('new_paste.html') @[Link]('/<int:paste_id>') def show_paste(paste_id): paste = [Link].get_or_404(paste_id) return render_template('show_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/', methods=['GET', 'POST']) def new_paste(): if [Link] == 'POST' and [Link]['code']: paste = Paste([Link], [Link]['code']) [Link](paste) [Link]() return redirect(url_for('show_paste', paste_id=[Link])) return render_template('new_paste.html') @[Link]('/<int:paste_id>') def show_paste(paste_id): paste = [Link].get_or_404(paste_id) return render_template('show_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/', methods=['GET', 'POST']) def new_paste(): if [Link] == 'POST' and [Link]['code']: paste = Paste([Link], [Link]['code']) [Link](paste) [Link]() return redirect(url_for('show_paste', paste_id=[Link])) return render_template('new_paste.html') @[Link]('/<int:paste_id>') def show_paste(paste_id): paste = [Link].get_or_404(paste_id) return render_template('show_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/', methods=['GET', 'POST']) def new_paste(): if [Link] == 'POST' and [Link]['code']: paste = Paste([Link], [Link]['code']) [Link](paste) [Link]() return redirect(url_for('show_paste', paste_id=[Link])) return render_template('new_paste.html') @[Link]('/<int:paste_id>') def show_paste(paste_id): paste = [Link].get_or_404(paste_id) return render_template('show_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/', methods=['GET', 'POST']) def new_paste(): if [Link] == 'POST' and [Link]['code']: paste = Paste([Link], [Link]['code']) [Link](paste) [Link]() return redirect(url_for('show_paste', paste_id=[Link])) return render_template('new_paste.html') @[Link]('/<int:paste_id>') def show_paste(paste_id): paste = [Link].get_or_404(paste_id) return render_template('show_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/', methods=['GET', 'POST']) def new_paste(): if [Link] == 'POST' and [Link]['code']: paste = Paste([Link], [Link]['code']) [Link](paste) [Link]() return redirect(url_for('show_paste', paste_id=[Link])) return render_template('new_paste.html') @[Link]('/<int:paste_id>') def show_paste(paste_id): paste = [Link].get_or_404(paste_id) return render_template('show_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/', methods=['GET', 'POST']) def new_paste(): if [Link] == 'POST' and [Link]['code']: paste = Paste([Link], [Link]['code']) [Link](paste) [Link]() return redirect(url_for('show_paste', paste_id=[Link])) return render_template('new_paste.html') @[Link]('/<int:paste_id>') def show_paste(paste_id): paste = [Link].get_or_404(paste_id) return render_template('show_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/', methods=['GET', 'POST']) def new_paste(): if [Link] == 'POST' and [Link]['code']: paste = Paste([Link], [Link]['code']) [Link](paste) [Link]() return redirect(url_for('show_paste', paste_id=[Link])) return render_template('new_paste.html') @[Link]('/<int:paste_id>') def show_paste(paste_id): paste = [Link].get_or_404(paste_id) return render_template('show_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/', methods=['GET', 'POST']) def new_paste(): if [Link] == 'POST' and [Link]['code']: paste = Paste([Link], [Link]['code']) [Link](paste) [Link]() return redirect(url_for('show_paste', paste_id=[Link])) return render_template('new_paste.html') @[Link]('/<int:paste_id>') def show_paste(paste_id): paste = [Link].get_or_404(paste_id) return render_template('show_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/<int:paste_id>/delete', methods=['GET', 'POST']) def delete_paste(paste_id): paste = [Link].get_or_404(paste_id) if [Link] is None or [Link] != [Link]: abort(401) if [Link] == 'POST': if 'yes' in [Link]: [Link](paste) [Link]() return redirect(url_for('new_paste')) else: return redirect(url_for('show_paste', paste_id=[Link])) return render_template('delete_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/<int:paste_id>/delete', methods=['GET', 'POST']) def delete_paste(paste_id): paste = [Link].get_or_404(paste_id) if [Link] is None or [Link] != [Link]: abort(401) if [Link] == 'POST': if 'yes' in [Link]: [Link](paste) [Link]() return redirect(url_for('new_paste')) else: return redirect(url_for('show_paste', paste_id=[Link])) return render_template('delete_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/<int:paste_id>/delete', methods=['GET', 'POST']) def delete_paste(paste_id): paste = [Link].get_or_404(paste_id) if [Link] is None or [Link] != [Link]: abort(401) if [Link] == 'POST': if 'yes' in [Link]: [Link](paste) [Link]() return redirect(url_for('new_paste')) else: return redirect(url_for('show_paste', paste_id=[Link])) return render_template('delete_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/<int:paste_id>/delete', methods=['GET', 'POST']) def delete_paste(paste_id): paste = [Link].get_or_404(paste_id) if [Link] is None or [Link] != [Link]: abort(401) if [Link] == 'POST': if 'yes' in [Link]: [Link](paste) [Link]() return redirect(url_for('new_paste')) else: return redirect(url_for('show_paste', paste_id=[Link])) return render_template('delete_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/<int:paste_id>/delete', methods=['GET', 'POST']) def delete_paste(paste_id): paste = [Link].get_or_404(paste_id) if [Link] is None or [Link] != [Link]: abort(401) if [Link] == 'POST': if 'yes' in [Link]: [Link](paste) [Link]() return redirect(url_for('new_paste')) else: return redirect(url_for('show_paste', paste_id=[Link])) return render_template('delete_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/<int:paste_id>/delete', methods=['GET', 'POST']) def delete_paste(paste_id): paste = [Link].get_or_404(paste_id) if [Link] is None or [Link] != [Link]: abort(401) if [Link] == 'POST': if 'yes' in [Link]: [Link](paste) [Link]() return redirect(url_for('new_paste')) else: return redirect(url_for('show_paste', paste_id=[Link])) return render_template('delete_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/<int:paste_id>/delete', methods=['GET', 'POST']) def delete_paste(paste_id): paste = [Link].get_or_404(paste_id) if [Link] is None or [Link] != [Link]: abort(401) if [Link] == 'POST': if 'yes' in [Link]: [Link](paste) [Link]() return redirect(url_for('new_paste')) else: return redirect(url_for('show_paste', paste_id=[Link])) return render_template('delete_paste.html', paste=paste)
Step 6 View Functions
@[Link]('/my-pastes') def my_pastes(): if [Link] is None: return redirect(url_for('login', next=[Link])) pastes = [Link].filter_by(user=[Link]).all() return render_template('my_pastes.html', pastes=pastes)
Step 6 View Functions
@[Link]('/my-pastes') def my_pastes(): if [Link] is None: return redirect(url_for('login', next=[Link])) pastes = [Link].filter_by(user=[Link]).all() return render_template('my_pastes.html', pastes=pastes)
Step 6 View Functions
@[Link]('/my-pastes') def my_pastes(): if [Link] is None: return redirect(url_for('login', next=[Link])) pastes = [Link].filter_by(user=[Link]).all() return render_template('my_pastes.html', pastes=pastes)
Step 6 View Functions
@[Link]('/my-pastes') def my_pastes(): if [Link] is None: return redirect(url_for('login', next=[Link])) pastes = [Link].filter_by(user=[Link]).all() return render_template('my_pastes.html', pastes=pastes)
Step 7 Templates
<!doctype html> <title>{% block title %}{% endblock %} | Flask Pastebin</title> <link rel=stylesheet type=text/css href="{{ url_for('static', filename='[Link]') }}"> <div class=page> <h1>Flask Pastebin</h1> <ul class=nav> <li><a href="{{ url_for('new_paste') }}">New Paste</a> {% if [Link] %} <li><a href="{{ url_for('my_pastes') }}">My Pastes</a> <li><a href="{{ url_for('logout') }}">Sign out ({{ [Link].display_name }})</a> {% else %} <li><a href="{{ url_for('login') }}">Sign in with Facebook</a> {% endif %} </ul> {% block body %}{% endblock %} </div> [Link]
Step 7 Templates
<!doctype html> <title>{% block title %}{% endblock %} | Flask Pastebin</title> <link rel=stylesheet type=text/css href="{{ url_for('static', filename='[Link]') }}"> <div class=page> <h1>Flask Pastebin</h1> <ul class=nav> <li><a href="{{ url_for('new_paste') }}">New Paste</a> {% if [Link] %} <li><a href="{{ url_for('my_pastes') }}">My Pastes</a> <li><a href="{{ url_for('logout') }}">Sign out ({{ [Link].display_name }})</a> {% else %} <li><a href="{{ url_for('login') }}">Sign in with Facebook</a> {% endif %} </ul> {% block body %}{% endblock %} </div> [Link]
Step 7 Templates
<!doctype html> <title>{% block title %}{% endblock %} | Flask Pastebin</title> <link rel=stylesheet type=text/css href="{{ url_for('static', filename='[Link]') }}"> <div class=page> <h1>Flask Pastebin</h1> <ul class=nav> <li><a href="{{ url_for('new_paste') }}">New Paste</a> {% if [Link] %} <li><a href="{{ url_for('my_pastes') }}">My Pastes</a> <li><a href="{{ url_for('logout') }}">Sign out ({{ [Link].display_name }})</a> {% else %} <li><a href="{{ url_for('login') }}">Sign in with Facebook</a> {% endif %} </ul> {% block body %}{% endblock %} </div> [Link]
Step 7 Templates
<!doctype html> <title>{% block title %}{% endblock %} | Flask Pastebin</title> <link rel=stylesheet type=text/css href="{{ url_for('static', filename='[Link]') }}"> <div class=page> <h1>Flask Pastebin</h1> <ul class=nav> <li><a href="{{ url_for('new_paste') }}">New Paste</a> {% if [Link] %} <li><a href="{{ url_for('my_pastes') }}">My Pastes</a> <li><a href="{{ url_for('logout') }}">Sign out ({{ [Link].display_name }})</a> {% else %} <li><a href="{{ url_for('login') }}">Sign in with Facebook</a> {% endif %} </ul> {% block body %}{% endblock %} </div> [Link]
Step 7 Templates
{% extends "[Link]" %} {% block title %}New Paste{% endblock %} {% block body %} <h2>New Paste</h2> <form action="" method=post> <div class=code><textarea name=code cols=60 rows=18></textarea></div> <p><input type=submit value="New Paste"> </form> {% endblock %}
new_paste.html
Step 7 Templates
{% extends "[Link]" %} {% block title %}New Paste{% endblock %} {% block body %} <h2>New Paste</h2> <form action="" method=post> <div class=code><textarea name=code cols=60 rows=18></textarea></div> <p><input type=submit value="New Paste"> </form> {% endblock %}
new_paste.html
Step 7 Templates
{% extends "[Link]" %} {% block title %}New Paste{% endblock %} {% block body %} <h2>New Paste</h2> <form action="" method=post> <div class=code><textarea name=code cols=60 rows=18></textarea></div> <p><input type=submit value="New Paste"> </form> {% endblock %}
new_paste.html
Step 7 Templates
{% extends "[Link]" %} {% block title %}Delete Paste #{{ [Link] }}{% endblock %} {% block body %} <h2>Delete Paste #{{ [Link] }}</h2> <form action="" method=post> <p>Are you sure you want to delete the paste? You cannot undo this. <p> <input type=submit name=yes value=Yes> <input type=submit name=no value=No> </form> {% endblock %}
delete_paste.html
Step 7 Templates
{% extends "[Link]" %} {% block title %}My Pastes{% endblock %} {% block body %} <h2>My Pastes</h2> <ul> {% for paste in pastes %} <li><a href="{{ url_for('show_paste', paste_id=[Link]) }}">#{{ [Link] }}</a> from {{ paste.pub_date.strftime('%Y-%m-%d @ %H:%M') }} {% endfor %} </ul> {% endblock %}
my_pastes.html
Step 8 CSS
body { margin: 0; padding: 0; } body, input { font-size: 16px; font-family: 'Helvetica Neue', sans-serif; } .page { margin: 50px auto; width: 740px; } h1 { margin: 0; font-weight: normal; color: #c00; } a { color: black; } a:hover { color: #c00; } .nav { margin: 0 0 20px 0; list-style: none; padding: 0; } .nav li { display: inline; } .nav li + li:before { content: " // "; } h2 { font-weight: normal; margin: 0; } dl { overflow: auto; font-size: 14px; } dl dt { font-weight: bold; width: 90px; float: left; clear: left; } dl dd { float: left; margin: 0; padding: 0; } pre, textarea { font-family: 'Consolas', monospace; font-size: 14px; background: #eee; padding: 0; margin: 0; } textarea { border: none; width: 720px; } .code, .flash { background: #eee; margin: 10px -30px; padding: 10px 30px; }
Step 9 Flashing
{% for message in get_flashed_messages() %} <p class=flash>{{ message }} {% endfor %}
Step 9 Flashing
from flask import flash @[Link]('/logout') def logout(): [Link]() flash('You were logged out') return redirect(url_for('new_paste'))
Demo
Debugging
Interactive Shell
?
These slides: [Link]