Skip to content
This repository was archived by the owner on Jun 19, 2025. It is now read-only.

Commit d069c60

Browse files
committed
Fix up spacing in extras
Few copy editing things
1 parent c764a65 commit d069c60

File tree

3 files changed

+39
-36
lines changed

3 files changed

+39
-36
lines changed

extras/css.md

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,10 @@ CSS Frameworks make it easier to manage styles for these larger, more complicate
1717

1818
Here is an example of a two-column layout:
1919

20-
21-
<div class="row">
22-
<div class="column-3">Left sidebar</div>
23-
<div class="column-9">Main content</div>
24-
</div>
20+
<div class="row">
21+
<div class="column-3">Left sidebar</div>
22+
<div class="column-9">Main content</div>
23+
</div>
2524

2625
**Typographical reset**. This is a font reset that looks a little more pleasing to the eye. It sets things like line spacing and font size.
2726

@@ -46,18 +45,18 @@ There are in fact a few entire languages that are dedicated to CSS. These langua
4645

4746
A common problem is how to deal with colours. For example if you had a corporate colour scheme of `#3311FF` your CSS would be littered with `#3311FF` references:
4847

49-
.nav { background-color: #3311FF; }
50-
.button { border-color: #3311FF; }
51-
.cake .icing { color: #3311FF; }
48+
.nav { background-color: #3311FF; }
49+
.button { border-color: #3311FF; }
50+
.cake .icing { color: #3311FF; }
5251

5352
In a CSS language you would be able to use a variable instead:
5453

55-
$corporate_color: #3311FF;
56-
.nav { background-color: $corporate_color; }
57-
.button { border-color: $corporate_color; }
58-
.cake .icing { color: $corporate_color; }
54+
$corporate_color: #3311FF;
55+
.nav { background-color: $corporate_color; }
56+
.button { border-color: $corporate_color; }
57+
.cake .icing { color: $corporate_color; }
5958

60-
Use of a CSS language is very common in large websites these days. Here are some of the more popular ones in use today:
59+
And if you later decided that the colour needed to be #3311EE instead, there would only be one place you needed to change it! Use of a CSS language is very common in large websites these days. Here are some of the more popular ones in use today:
6160

6261
* [SASS](http://sass-lang.com/) is one of the original CSS languages. It uses the Ruby programming language under the hood. You might like to try the [Python](https://pypi.python.org/pypi/pyScss/1.1.5) port which is compatible with SASS 3.2. You can also take a look at [Compass](http://compass-style.org/) which pushes SASS even further.
6362
* [LESS](http://lesscss.org/) has a very similar philosophy. It is written in JavaScript, so it can either be run in the browser or, using Node, on the server.

extras/databases.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,22 @@ title: Databases
55

66
There is a reason why we haven't used a more permanent method for storing our email addresses, and that's because _databases are complicated_. Seriously.
77

8-
But fortunately they are not that difficult once you get the hang of it. Since the 1970s many databases have standardised on using the **SQL** language. It defines how to store and search data in _tables_, which contain _columns_. If you learn SQL then you can use quite a lot of different databases.
8+
But fortunately they are not that difficult once you get the hang of it. Since the 1970s many databases have standardised on using the **SQL** language. It defines how to store and search data in _tables_, which contain _columns_, and rows of data usually referred to as _records_. If you learn SQL then you can use quite a lot of different databases.
99

10-
Because of their size and complexity databases are generally written as their own separate servers that run in addition to your web server. That comes with additional work that we probably don't need at this moment. For now we'll use [SQLite](http://www.sqlite.org/) which is a very widely used database engine that just happens to come bundled in Python.
10+
Because of their size and complexity databases are generally written as their own separate servers that run in addition to your web server. That comes with additional work that we probably don't need at this moment. For now we'll use [SQLite](http://www.sqlite.org/) which is a simple and very widely used database engine that just happens to come bundled in Python.
1111

1212
## Creating the database
1313

1414
Since Python 2.5 the SQLite library has shipped in the standard distribution. This means it should be available already. You can import the `sqlite3` library in a Python shell to see if it works:
1515

16-
>>> import sqlite3
16+
>>> import sqlite3
1717

1818
We are going to start by creating a database in a file called `emails.db`. It will have one table called `email_addresses` which will keep all our emails. Make sure your Python shell started in the same directory as your website code.
1919

20-
>>> conn = sqlite3.connect("emails.db")
21-
>>> cursor = conn.cursor()
22-
>>> cursor.execute("CREATE TABLE email_addresses ( email TEXT );")
23-
<sqlite3.Cursor object at 0xb7467ce0>
20+
>>> conn = sqlite3.connect("emails.db")
21+
>>> cursor = conn.cursor()
22+
>>> cursor.execute("CREATE TABLE email_addresses ( email TEXT );")
23+
<sqlite3.Cursor object at 0xb7467ce0>
2424

2525
Here you can see we connected to `emails.db` (this file didn't exist, so SQLite created it). We opened a _cursor_, which is what allows us to send commands, and executed a _CREATE TABLE_ statement to create the email addresses table. It has one column, _email_, which can just be a string of text.
2626

@@ -30,21 +30,21 @@ The Flask documentation has a [section](http://flask.pocoo.org/docs/patterns/sql
3030

3131
We'll need to import the `g` object from Flask, as well as `sqlite3`:
3232

33-
from flask import g
34-
import sqlite3
33+
from flask import g
34+
import sqlite3
3535

3636
Now we use `@app.before_request` to run a function before every request from the browser:
3737

38-
@app.before_request
39-
def before_request():
40-
g.db = sqlite3.connect("emails.db")
38+
@app.before_request
39+
def before_request():
40+
g.db = sqlite3.connect("emails.db")
4141

4242
Likewise we use `@app.teardown_request` to close the database connection after every request.
4343

44-
@app.teardown_request
45-
def teardown_request(exception):
46-
if hasattr(g, 'db'):
47-
g.db.close()
44+
@app.teardown_request
45+
def teardown_request(exception):
46+
if hasattr(g, 'db'):
47+
g.db.close()
4848

4949
## Adding a new email address
5050

@@ -65,15 +65,15 @@ Now that we have all our emails stored in a database we have to use a _SELECT_ s
6565

6666
@app.route('/emails.html')
6767
def emails():
68-
email_addresses = g.db.execute("SELECT email FROM email_addresses").fetchall()
69-
return render_template('emails.html', email_addresses = email_addresses)
68+
email_addresses = g.db.execute("SELECT email FROM email_addresses").fetchall()
69+
return render_template('emails.html', email_addresses=email_addresses)
7070

7171
You might notice that the list of emails now looks a little strange on the web page. This is because the `g.db.execute()` statement returns an entire tuple for _every_ email address. In the Python console it looks like this:
7272

73-
>>> db.execute('select * from email_addresses').fetchall()
74-
[(u'eroaskdlg',), (u'kjzdfhks',), (u'lksrlajkr',)]
73+
>>> db.execute('select * from email_addresses').fetchall()
74+
[(u'eroaskdlg',), (u'kjzdfhks',), (u'lksrlajkr',)]
7575

76-
So every email is actually a list. The email itself is at position 0 in the list. So update the emails template to use position 0:
76+
So every item in the list is actually a tuple (a non-modifiable list). The email itself is at position 0 in each tuple. So update the emails template to print just the first element:
7777

7878
{% raw %}
7979

@@ -85,7 +85,7 @@ So every email is actually a list. The email itself is at position 0 in the list
8585

8686
{% endraw %}
8787

88-
And that's it! You can now restart the web server as many times as you like! All the emails are now stored directly in the database.
88+
And that's it! You can now restart the web server as many times as you like, and your list of emails will remain! All the emails are now stored directly in the database.
8989

9090
## Further Reading
9191

extras/sessions.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ It sure does, and they're very simple to use. Firstly, **add `session` as anothe
2121

2222
Then you need to give flask a secret key to use, to make sure the session is secure. To get a nice secret key, **run this at a command prompt**:
2323

24-
python -c "import os; print repr(os.urandom(24))"
24+
python -c "import os; print repr(os.urandom(24))"
2525
2626
and copy the string you get. To set this as the flask app's secret key, just **add the following line** after you initialize your `app` (use your own key!):
2727

@@ -69,4 +69,8 @@ Here, we use a few `if` checks to make sure that our user added an email address
6969

7070
* Allow the app to remember when a user has already registered their email, and not show them an email input form when they have (maybe say Thanks! for signing up). Check out the [Jinja2 template documentation](http://jinja.pocoo.org/docs/templates/) if you'd like to use a little template logic to help with this. You could change the above button so that it also only shows after registering an email.
7171

72+
Extra points:
73+
7274
* Add a "protected" page which allows you to delete any email address, and a very simple admin login system (with just a single password) to access it. You can use a session to determine whether someone is currently logged in or not. This might be a little more difficult, but any challengers are welcome to try it out! You can check out the code sample [here](http://flask.pocoo.org/docs/quickstart/#sessions) for some hints on how to go about that.
75+
76+
* Integrate these features into using your databases as needed

0 commit comments

Comments
 (0)