Flaskr: Tutorial with extra comments

Here is the Flask tutorial file with extra commenting:

import sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
from contextlib import closing

# configuration
DATABASE = 'flaskr.db'
# DEBUG must be set to False in production or interactive debugger can be used
DEBUG = True
# SECRET_KEY keeps client sessions secure (e.g. to sign cookies).  It should be set to a complex random value.
# the following code can be used to generate a good key:
# >>> import os, base64
# >>> base64.urlsafe_b64encode(os.urandom(30))
SECRET_KEY = 'development key'
USERNAME = 'admin'
PASSWORD = 'default'

app = Flask(__name__)
# from_object will look at the given object and look for all UPPERCASE variables (e.g. DATABASE, DEBUG)
# you can force Flask top use a configuration file based on the environment using:
#     app.config.from_envvar('FLASKR_SETTINGS", silent=True)
# this will make Flask read an environmental variable containing the location of the settings file.
# the silent=True ensures that no complaint is made if the variable is missing - Flask will then use the defaults.
app.config.from_object(__name__)

def connect_db():
    return sqlite3.connect(app.config['DATABASE'])

# This function initialises the database and creates the tables within the sql file
def init_db():
    # http://docs.python.org/dev/library/contextlib.html#contextlib.closing
    # closing() ensures that the connection remains open for the duration of the with block.
    with closing(connect_db()) as db:
        # app.open_resources opens one of the resources from the application's folder (e.g. /static/picture.jpg)
        with app.open_resource('schema.sql') as f:
            db.cursor().executescript(f.read())
        db.commit()

# the before_request() will always be called before a database connection
@app.before_request
def before_request():
    # g is a special object provided by Flask that stores information from one request only.
    g.db = connect_db()

# teardown_request() gets called after reponse has been constructed - will always be called after exception
# after_request() can also be used, but is not guaranteed to be called when an exception is raised.
@app.teardown_request
def teardown_request(exception):
    g.db.close()

# app.route tells flask what url should trigger the function
# it can be made to accept parameters:
# >>> app.route('/user/')
# --> return username
# Or:
# >>> app.route('/post/') # or float or path (allows slashes)
# --> return post_id
@app.route('/')
def show_entries():
    # this will return entries as tuples
    # to convert to a dictionary instead: http://flask.pocoo.org/docs/patterns/sqlite3/#easy-querying
    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)

# the methods parameter ensures that only certain requests are processed - in this example, only POST requests.
@app.route('/add', methods=['POST'])
def add_entry():
    if not session.get('logged_in'):
        abort(401)
    # always use question marks to stop the ability to use SQL injection
    g.db.execute('insert into entries (title, text) values (?, ?)',
                 [request.form['title'], request.form['text']])
    g.db.commit()
    # the flash() allows a message to be recorded and accessed in the next request:
    # http://flask.pocoo.org/docs/patterns/flashing/
    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'] != app.config['USERNAME']:
            error = 'Invalid username'
        elif request.form['password'] != app.config['PASSWORD']:
            error = 'Invalid password'
        else:
            # sessions back it possible to remember information between requests by using a signed cookie.
            # for more about sessions - http://flask.pocoo.org/docs/api/#sessions
            session['logged_in'] = True
            flash('You were logged in')
            # flask.redirect(location, code=302) redirects client to a target location - supports codes 301,303,305,307
            # url_for(endpoint) generates a url to the given endpoint
            # see http://flask.pocoo.org/docs/quickstart/#url-building
            return redirect(url_for('show_entries'))
    # render_template(template_name_or_list, **context) renders a template from the templates folder.
    # see http://flask.pocoo.org/docs/api/#template-rendering
    # for more on Jinja2 in flask, see http://flask.pocoo.org/docs/templating/
    # also http://jinja.pocoo.org/docs/templates/
    return render_template('login.html', error=error)

@app.route('/logout')
def logout():
    # the dictionary pop() with the second parameter as "None" deleted the key from the dictionary.
    # if there's nothing there, nothing happens --> don't have to ensure that a user is already logged-in.
    session.pop('logged_in', None)
    flash('You were logged out')
    return redirect(url_for('show_entries'))

if __name__ == '__main__':
    app.run()

Additionally, here is the layout.html file with extra commenting:






    Flaskr
    
    

    

Flaskr

{% if not session.logged_in %} log in {% else %} log out {% endif %}
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %} {% block body %}{% endblock %}