Coding Bootcamp: Introduction to Flask - Part I

What is Flask?

Flask dependencies

How to handle dependencies

How to install virtualenv on Machintosh or Linux

$ sudo pip install virtualenv

How to install virtualenv on Ubuntu

$ sudo apt-get install python-virtualenv

How to install virtualenv on Microsoft Windows

$ pip install --upgrade pip setuptools
$ pip install virtualenv

How to create a new Flask project I

$ mkdir app
$ cd app

How to create a new Flask project II

$ virtualenv venv

on Mac OS X or Linux

$ . venv/bin/activate

on Microsoft Windows

$ venv\scripts\activate

How to create a new Flask project III

$ pip install Flask
$ deactivate

A minimal app I

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'
    
if __name__ == '__main__':
   app.run(debug = True)

A minimal app II

$ cd ./app
$ export FLASK_APP=hello.py
$ flask run
 * Running on http://127.0.0.1:5000/

A minimal app III

Variable rules I

@app.route('/hello/')
@app.route('/hello/<name>')
def hello_name(name):
   return 'Hello %s!' % name

Variable rules II

Variable rules III

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return 'Post %d' % post_id

Variable rules IV

Unique URLs / Redirection behaviour

@app.route('/projects/')
def projects():
    return 'The project page'

@app.route('/about')
def about():
    return 'The about page'

URL building I

URL building II

>>> from flask import Flask, url_for
>>> app = Flask(__name__)
>>> @app.route('/')
... def index(): pass
...
>>> @app.route('/login')
... def login(): pass
...
>>> @app.route('/user/<username>')
... def profile(username): pass
...
>>> with app.test_request_context():
...  print (url_for('index'))
...  print (url_for('login'))
...  print (url_for('profile', username='mark'))
...

HTTP Methods

Request example

from flask import request

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        do_the_login()
    else:
        show_the_login_form()

Static files I

from flask import send_from_directory
import os
@app.route('/static/css/style.css')
def serve_static_css(filename):
    root_dir = os.path.dirname(os.getcwd())
    return send_from_directory(os.path.join(root_dir, 'static', 'css'), filename)

Static files II

<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">

Rendering Templates

from flask import render_template
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

Template Example

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Hello from Flask</title>
  </head>
  <body>
        {% if name %}
          <h1>Hello {{ name }}!</h1>
        {% else %}
          <h1>Hello, Flask!</h1>
        {% endif %}
  </body>
</html>

Result

Create a form I

$ pip install Flask-WTF

Create a form II

<form action="/new" method = "post">
     <label for = "name">Name</label>
     <input type = "text" name = "name" placeholder = "name"/>
     <br>
     <label for = "surname">Surname</label>
     <input type = "text" name = "surname" placeholder = "surname"/>
     <br>
     <label for = "email">Email</label>
     <input type = "text" name = "email" placeholder = "email"/>
     <br>
     <label for = "password">Password</label>
     <input type = "password" name = "password" placeholder = "password"/>
     <br>
     <input id="btnSignUp" type = "submit" value = "Sign up"/>
</form>

Create a form III

from flask import Flask
from flask_wtf import Form
from wtforms import TextField, SubmitField, PasswordField

class ContactForm(Form):
   name = TextField("Name")
   surname = TextField("Surname")
   email = TextField("Email")
   password = PasswordField('Password')
   submit = SubmitField("Send")

Create a form IV

from flask import Flask, request, render_template
from forms import ContactForm
@app.route('/new', methods = ['GET', 'POST'])
def new():
    if (request.method == 'POST'):
        pass
    return render_template('new.html')

Message flashing I

from flask import Flask, url_for, flash, send_from_directory, request, redirect, render_template
from forms import ContactForm
@app.route('/new', methods = ['GET', 'POST'])
def new():
    if (request.method == 'POST'):
        if (not request.form['name'] or not request.form['surname'] \
                or not request.form['email'] or not request.form['password']):
            flash('Please fill all the fields.', 'error')
        else:
            return redirect(url_for('index'))
    return render_template('new.html')
    
@app.route('/')
def index():
   return render_template('index.html') # returns a simple .html page

Message flashing II

{%- for category, message in get_flashed_messages(with_categories = true) %}
    <div>
    {{ message }}
    </div>
{%- endfor %}

Message flashing III

app.secret_key = 'random string'

Sessions I

from flask import ..., session

Sessions II

session['email'] = 'foo@bar.com'
session.pop('email', None)

Sessions III

@app.route('/new', methods = ['GET', 'POST'])
def new():
    if (request.method == 'POST'):
        if (not request.form['name'] or not request.form['surname'] \
                or not request.form['email'] or not request.form['password']):
            flash('Please fill all the fields.', 'error')
        else:
            session['name'] = request.form['name']
            return login() 
    return render_template('new.html')

Sessions IV

app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

Log-in

@app.route('/login', methods=['POST'])
def login():
    if 'name' in session:
        name = session['name']
        return 'You are logged in as ' + name + '<br>' + \
         "<b><a href = '/logout'>click here to log out</a></b>"
    return "You are not logged in <br><a href = '/login'></b>" + \
      "click here to log in</b></a>"

Log-out

@app.route('/logout')
def logout():
   # remove the name from the session if it is there
   session.pop('name', None)
   return redirect(url_for('index'))

Exercise 1.1

Exercise 1.2

Exercise 1.3

In views.py add a function called login that:

Exercise 1.3 (continued)

Exercise 1.4

Exercise 1.5

Reference


Creative Commons Licence
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.