Skip to content

Commit b8b735d

Browse files
committed
Merge branch 'master' of github.com:cewing/training.python_web
2 parents 7d818c2 + 7260a35 commit b8b735d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+3305
-42
lines changed

assignments/teachers/week04/answers/homework.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def __init__(self, db, urls):
1919

2020
def __call__(self, environ, start_response):
2121
headers = [('Content-type', 'text/html')]
22+
import pdb; pdb.set_trace( )
2223
try:
2324
path = environ.get('PATH_INFO', None)
2425
if path is None:
@@ -44,9 +45,9 @@ def __call__(self, environ, start_response):
4445
def books(self):
4546
core = ['<h1>Book Database</h1>',
4647
'<ul>']
47-
tmpl = '<li><a href="http://github.com/book/%s">%s</a></li>'
48-
for book_id, book_data in self.db.items():
49-
core.append(tmpl % (book_id, book_data['title']))
48+
tmpl = '<li><a href="http://github.com/book/%%3Cspan%20class="x x-first x-last">(id)s">%(title)s</a></li>'
49+
for data in self.db.titles():
50+
core.append(tmpl % data)
5051
core.append('</ul>')
5152
body = "\n".join(core)
5253
context = {'page_title': "Book Database",
@@ -66,9 +67,10 @@ def book(self, id):
6667
</dl>
6768
<p><a href="../">More Books</a></p>
6869
"""
69-
book = self.db.get(id, None)
70-
if book is None:
71-
raise NameError
70+
try:
71+
book = self.db.title_info(id)
72+
except KeyError:
73+
raise NameError('book not found')
7274
title = "Book Database: %s" % book['isbn']
7375
context = {'page_title': title,
7476
'page_body': tmpl % book}
@@ -99,7 +101,7 @@ def _get_callable(self, path):
99101
# this block will be called when the script is run directly
100102
from wsgiref.simple_server import make_server
101103
import bookdb
102-
application = MyApplication(bookdb.database, URLS)
104+
application = MyApplication(bookdb.BookDB(), URLS)
103105
srv = make_server('localhost', 8080, application)
104106
srv.serve_forever()
105107
else:
@@ -114,4 +116,4 @@ def _get_callable(self, path):
114116
import sys
115117
sys.path.append('/path/to/directory/containing/bookdb/on/server')
116118
import bookdb
117-
application = MyApplication(bookdb.database, URLS)
119+
application = MyApplication(bookdb.BookDB(), URLS)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from flask import Flask
2+
from flask import render_template
3+
4+
import bookdb
5+
6+
app = Flask(__name__)
7+
8+
db = bookdb.BookDB()
9+
10+
11+
@app.route('/')
12+
def books():
13+
books = db.titles()
14+
return render_template('book_list.html', books=books)
15+
16+
17+
@app.route('/book/<book_id>/')
18+
def book(book_id):
19+
book = db.title_info(book_id)
20+
return render_template('book_detail.html', book=book)
21+
22+
23+
if __name__ == '__main__':
24+
app.run(debug=True)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
2+
3+
class BookDB():
4+
def titles(self):
5+
titles = [dict(id=id, title=database[id]['title']) for id in database.keys()]
6+
return titles
7+
8+
def title_info(self, id):
9+
return database[id]
10+
11+
12+
# let's pretend we're getting this information from a database somewhere
13+
database = {
14+
'id1' : {'title' : 'CherryPy Essentials: Rapid Python Web Application Development',
15+
'isbn' : '978-1904811848',
16+
'publisher' : 'Packt Publishing (March 31, 2007)',
17+
'author' : 'Sylvain Hellegouarch',
18+
},
19+
'id2' : {'title' : 'Python for Software Design: How to Think Like a Computer Scientist',
20+
'isbn' : '978-0521725965',
21+
'publisher' : 'Cambridge University Press; 1 edition (March 16, 2009)',
22+
'author' : 'Allen B. Downey',
23+
},
24+
'id3' : {'title' : 'Foundations of Python Network Programming',
25+
'isbn' : '978-1430230038',
26+
'publisher' : 'Apress; 2 edition (December 21, 2010)',
27+
'author' : 'John Goerzen',
28+
},
29+
'id4' : {'title' : 'Python Cookbook, Second Edition',
30+
'isbn' : '978-0-596-00797-3',
31+
'publisher' : 'O''Reilly Media',
32+
'author' : 'Alex Martelli, Anna Ravenscroft, David Ascher',
33+
},
34+
'id5' : {'title' : 'The Pragmatic Programmer: From Journeyman to Master',
35+
'isbn' : '978-0201616224',
36+
'publisher' : 'Addison-Wesley Professional (October 30, 1999)',
37+
'author' : 'Andrew Hunt, David Thomas',
38+
},
39+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>{{ book.title }}</title>
5+
</head>
6+
<body>
7+
<h1>{{ book.title }}</h1>
8+
<dl>
9+
<dt>Author</dt><dd>{{ book.author }}</dd>
10+
<dt>Publisher</dt><dd>{{ book.publisher }}</dd>
11+
<dt>ISBN</dt><dd>{{ book.isbn }}</dd>
12+
</dl>
13+
<p><a href="{{ url_for('books') }}">Back to the list</a></p>
14+
</body>
15+
</html>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>Python Books</title>
5+
</head>
6+
<body>
7+
<h1>Summer Reading</h1>
8+
<p>Here's a list of books you might enjoy. Click a title to read more
9+
about that book.</p>
10+
<ul>
11+
{% for book in books %}
12+
<li><a href="{{ url_for('book', book_id=book.id) }}">{{ book.title }}</a></li>
13+
{% endfor %}
14+
</ul>
15+
</body>
16+
</html>
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import sqlite3
2+
from contextlib import closing
3+
4+
from flask import Flask
5+
from flask import request
6+
from flask import session
7+
from flask import g
8+
from flask import redirect
9+
from flask import url_for
10+
from flask import abort
11+
from flask import render_template
12+
from flask import flash
13+
14+
# configuration
15+
DATABASE = '/tmp/flaskr.db'
16+
DEBUG = True
17+
SECRET_KEY = 'devkey'
18+
USERNAME = 'admin'
19+
PASSWORD = 'default'
20+
21+
22+
app = Flask(__name__)
23+
app.config.from_object(__name__)
24+
25+
def connect_db():
26+
return sqlite3.connect(app.config['DATABASE'])
27+
28+
29+
def init_db():
30+
with closing(connect_db()) as db:
31+
with app.open_resource('schema.sql') as f:
32+
db.cursor().executescript(f.read())
33+
db.commit()
34+
35+
36+
@app.before_request
37+
def before_request():
38+
g.db = connect_db()
39+
40+
41+
@app.teardown_request
42+
def teardown_request(exception):
43+
g.db.close()
44+
45+
46+
def get_all_entries():
47+
cur = g.db.execute('select title, text from entries order by id desc')
48+
entries = [dict(title=row[0], text=row[1]) for row in cur.fetchall()]
49+
return entries
50+
51+
52+
@app.route('/')
53+
def show_entries():
54+
entries = get_all_entries()
55+
return render_template('show_entries.html', entries=entries)
56+
57+
58+
@app.route('/add', methods=['POST'])
59+
def add_entry():
60+
if not session.get('logged_in'):
61+
abort(401)
62+
g.db.execute('insert into entries (title, text) values (?, ?)',
63+
[request.form['title'], request.form['text']])
64+
g.db.commit()
65+
flash('New entry was successfully posted')
66+
return redirect(url_for('show_entries'))
67+
68+
69+
@app.route('/login', methods=['GET', 'POST'])
70+
def login():
71+
error = None
72+
if request.method == 'POST':
73+
if request.form['username'] != app.config['USERNAME']:
74+
error = 'Invalid Username'
75+
elif request.form['password'] != app.config['PASSWORD']:
76+
error = 'Invalid Password'
77+
else:
78+
session['logged_in'] = True
79+
flash('You are logged in')
80+
return redirect(url_for('show_entries'))
81+
return render_template('login.html', error=error)
82+
83+
84+
@app.route('/logout')
85+
def logout():
86+
session.pop('logged_in', None)
87+
flash('You are now logged out')
88+
return redirect(url_for('show_entries'))
89+
90+
91+
if __name__ == '__main__':
92+
app.run()
93+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import os
2+
import flaskr
3+
import unittest
4+
import tempfile
5+
6+
7+
class FlaskrTestCase(unittest.TestCase):
8+
9+
def setUp(self):
10+
self.db_fd, flaskr.app.config['DATABASE'] = tempfile.mkstemp()
11+
flaskr.app.config['TESTING'] = True
12+
self.app = flaskr.app.test_client()
13+
flaskr.init_db()
14+
15+
def tearDown(self):
16+
os.close(self.db_fd)
17+
os.unlink(flaskr.app.config['DATABASE'])
18+
19+
20+
def login(self, username, password):
21+
return self.app.post('/login', data=dict(
22+
username=username,
23+
password=password
24+
), follow_redirects=True)
25+
26+
27+
def logout(self):
28+
return self.app.get('/logout', follow_redirects=True)
29+
30+
31+
def test_get_all_entries_empty(self):
32+
with self.app.test_request_context('/'):
33+
self.app.preprocess_request()
34+
entries = flaskr.get_all_entries()
35+
self.assertEquals(entries, [])
36+
37+
38+
if __name__ == '__main__':
39+
unittest.main()
40+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
drop table if exists entries;
2+
create table entries (
3+
id integer primary key autoincrement,
4+
title string not null,
5+
text string not null
6+
);

assignments/teachers/week05/answers/flaskr/static/css/bootstrap.min.css

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
8.57 KB
Loading

0 commit comments

Comments
 (0)