-
-
Notifications
You must be signed in to change notification settings - Fork 16.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added mini blogging application as Flask example.
This should become the tutorial.
- Loading branch information
Showing
7 changed files
with
241 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Flaskr | ||
~~~~~~ | ||
A microblog example application written as Flask tutorial with | ||
Flask and sqlite3. | ||
:copyright: (c) 2010 by Armin Ronacher. | ||
:license: BSD, see LICENSE for more details. | ||
""" | ||
from __future__ import with_statement | ||
import time | ||
import sqlite3 | ||
from contextlib import closing | ||
from flask import Flask, request, session, g, redirect, url_for, abort, \ | ||
render_template, flash | ||
from werkzeug import secure_filename | ||
|
||
# configuration | ||
DATABASE = '/tmp/flaskr.db' | ||
DEBUG = True | ||
SECRET_KEY = 'development key' | ||
USERNAME = 'admin' | ||
PASSWORD = 'default' | ||
|
||
# create our little application :) | ||
app = Flask(__name__) | ||
app.secret_key = SECRET_KEY | ||
app.debug = DEBUG | ||
|
||
|
||
def connect_db(): | ||
"""Returns a new connection to the database.""" | ||
return sqlite3.connect(DATABASE) | ||
|
||
|
||
def init_db(): | ||
"""Creates the database tables.""" | ||
with closing(connect_db()) as db: | ||
with app.open_resource('schema.sql') as f: | ||
db.cursor().executescript(f.read()) | ||
db.commit() | ||
|
||
|
||
@app.request_init | ||
def before_request(): | ||
"""Make sure we are connected to the database each request. Also | ||
set `g.logged_in` to `True` if we are logged in. | ||
""" | ||
g.db = connect_db() | ||
g.logged_in = session.get('logged_in', False) | ||
|
||
|
||
@app.request_shutdown | ||
def after_request(response): | ||
"""Closes the database again at the end of the request.""" | ||
g.db.close() | ||
return response | ||
|
||
|
||
@app.route('/') | ||
def show_entries(): | ||
cur = g.db.execute('select title, text from entries order by id desc') | ||
entries = [dict(title=row[0], text=row[1]) for row in cur.fetchall()] | ||
return render_template('show_entries.html', entries=entries) | ||
|
||
|
||
@app.route('/add', methods=['POST']) | ||
def add_entry(): | ||
if not g.logged_in: | ||
abort(401) | ||
g.db.execute('insert into entries (title, text) values (?, ?)', | ||
[request.form['title'], request.form['text']]) | ||
g.db.commit() | ||
flash('New entry was successfully posted') | ||
return redirect(url_for('show_entries')) | ||
|
||
|
||
@app.route('/login', methods=['GET', 'POST']) | ||
def login(): | ||
error = None | ||
if request.method == 'POST': | ||
if request.form['username'] != USERNAME: | ||
error = 'Invalid username' | ||
elif request.form['password'] != PASSWORD: | ||
error = 'Invalid password' | ||
else: | ||
session['logged_in'] = True | ||
flash('You were logged in') | ||
return redirect(url_for('show_entries')) | ||
return render_template('login.html', error=error) | ||
|
||
|
||
@app.route('/logout') | ||
def logout(): | ||
session.pop('logged_in', None) | ||
flash('You were logged out') | ||
return redirect(url_for('show_entries')) | ||
|
||
|
||
if __name__ == '__main__': | ||
app.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Flaskr Tests | ||
~~~~~~~~~~~~ | ||
Tests the Flaskr application. | ||
:copyright: (c) 2010 by Armin Ronacher. | ||
:license: BSD, see LICENSE for more details. | ||
""" | ||
import flaskr | ||
import unittest | ||
import tempfile | ||
|
||
|
||
class FlaskrTestCase(unittest.TestCase): | ||
|
||
def setUp(self): | ||
"""Before each test, set up a blank database""" | ||
self.db = tempfile.NamedTemporaryFile() | ||
self.app = flaskr.app.test_client() | ||
flaskr.DATABASE = self.db.name | ||
flaskr.init_db() | ||
|
||
def login(self, username, password): | ||
return self.app.post('/login', data=dict( | ||
username=username, | ||
password=password | ||
), follow_redirects=True) | ||
|
||
def logout(self): | ||
return self.app.get('/logout', follow_redirects=True) | ||
|
||
# testing functions | ||
|
||
def test_login_logout(self): | ||
"""Make sure login and logout works""" | ||
rv = self.login(flaskr.USERNAME, flaskr.PASSWORD) | ||
assert 'You were logged in' in rv.data | ||
rv = self.logout() | ||
assert 'You were logged out' in rv.data | ||
rv = self.login(flaskr.USERNAME + 'x', flaskr.PASSWORD) | ||
assert 'Invalid username' in rv.data | ||
rv = self.login(flaskr.USERNAME, flaskr.PASSWORD + 'x') | ||
assert 'Invalid password' in rv.data | ||
|
||
def test_messages(self): | ||
"""Test that messages work""" | ||
# start with a blank state | ||
rv = self.app.get('/') | ||
assert 'No entries here so far' in rv.data | ||
self.login(flaskr.USERNAME, flaskr.PASSWORD) | ||
rv = self.app.post('/add', data=dict( | ||
title='<Hello>', | ||
text='<strong>HTML</strong> allowed here' | ||
), follow_redirects=True) | ||
assert 'No entries here so far' not in rv.data | ||
self.login(flaskr.USERNAME, flaskr.PASSWORD) | ||
assert '<Hello>' in rv.data | ||
assert '<strong>HTML</strong> allowed here' in rv.data | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
drop table if exists entries; | ||
create table entries ( | ||
id integer primary key autoincrement, | ||
title string not null, | ||
text string not null | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
body { font-family: sans-serif; background: #eee; } | ||
a, h1, h2 { color: #377BA8; } | ||
h1, h2 { font-family: 'Georgia', serif; margin: 0; } | ||
h1 { border-bottom: 2px solid #eee; } | ||
h2 { font-size: 1.2em; } | ||
div.metanav { text-align: right; font-size: 0.8em; background: #fafafa; | ||
padding: 0.3em; margin-bottom: 1em; } | ||
ul.entries { list-style: none; margin: 0; padding: 0; } | ||
ul.entries li { margin: 0.8em 1.2em; } | ||
ul.entries li h2 { margin-left: -1em; } | ||
div.page { margin: 2em auto; width: 35em; border: 5px solid #ccc; | ||
padding: 0.8em; background: white; } | ||
form.add-entry { font-size: 0.9em; border-bottom: 1px solid #ccc; } | ||
form.add-entry dl { font-weight: bold; } | ||
div.flash { background: #CEE5F5; padding: 0.5em; border: 1px solid #AACBE2; } | ||
p.error { background: #F0D6D6; padding: 0.5em; } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<!doctype html> | ||
<title>Flaskr</title> | ||
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}"> | ||
<div class=page> | ||
<h1>Flaskr</h1> | ||
<div class=metanav> | ||
{% if not g.logged_in %} | ||
<a href="{{ url_for('login') }}">log in</a> | ||
{% else %} | ||
<a href="{{ url_for('logout') }}">log out</a> | ||
{% endif %} | ||
</div> | ||
{% for message in get_flashed_messages() %} | ||
<div class=flash>{{ message }}</div> | ||
{% endfor %} | ||
{% block body %}{% endblock %} | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{% extends "layout.html" %} | ||
{% block body %} | ||
<h2>Login</h2> | ||
{% if error %}<p class=error><strong>Error:</strong> {{ error }}{% endif %} | ||
<form action="{{ url_for('login') }}" method=post> | ||
<dl> | ||
<dt>Username: | ||
<dd><input type=text name=username> | ||
<dt>Password: | ||
<dd><input type=passowrd name=password> | ||
<dd><input type=submit value=Login> | ||
</dl> | ||
</form> | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{% extends "layout.html" %} | ||
{% block body %} | ||
{% if g.logged_in %} | ||
<form action="{{ url_for('add_entry') }}" method=post class=add-entry> | ||
<dl> | ||
<dt>Title: | ||
<dd><input type=text size=30 name=title> | ||
<dt>Text: | ||
<dd><textarea name=text rows=5 cols=40></textarea> | ||
<dd><input type=submit value=Share> | ||
</dl> | ||
</form> | ||
{% endif %} | ||
<ul class=entries> | ||
{% for entry in entries %} | ||
<li><h2>{{ entry.title }}</h2>{{ entry.text|safe }} | ||
{% else %} | ||
<li><em>Unbelievable. No entries here so far</em> | ||
{% endfor %} | ||
</ul> | ||
{% endblock %} |