Python and Flask
Python is high-level general purpose programming language. It's easy to learn and there are a lot of good resources available online. These notes do not aim to teach Python and only provide a brief overview of Flask.
Virtual environments
When doing a Python project, it's a good idea to contain it within a
virtual environment. This allows you to install a library for one
project without installing it everywhere. A good guide is
https://python.land/virtual-environments/virtualenv. In Python 3.4 and
above, you create the virtual environment by running
python -m venv [directory]. Usually you want the virtual environment
in your current directory, so run python -m venv venv. This will
create a virtual environment in a directory called venv.
To activate the virtual environment, run venv.bat on Windows or
source venv/bin/activate on Linux or MacOS. You have to activate the
virtual environment every time before you can use it. Once it's
activated anything you install will only be installed inside it. You can
then deactivate it by running deactivate.
Serialisation
Serialisation in Python is done using the pickle module.
>>> capitals = {'Greenland': 'Nuuk',
'Luxembourg': 'Luxembourg',
'Trinidad and Tobago': 'Port of Spain',
'Romania': 'Bucharest'}
>>> serialised = pickle.dumps(capitals)
>>> print(serialised)
b'\x80\x04\x95c\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\tGreenland\x94\x8c\x04Nuuk\x94\x8c\nLuxembourg\x94h\x03\x8c\x13Trinidad and Tobago\x94\x8c\rPort of Spain\x94\x8c\x07Romania\x94\x8c\tBucharest\x94u.'
>>> loaded = pickle.loads(serialised)
>>> loaded == capitals
True
Data can be serialised to bytes (binary which anything can store) and then deserialised back into a Python object. This is useful for databases as they can't store Python objects but they can store binary.
A more widely used form of serialisation (not Python specific) is JSON
(Javascript Object Notation). It is natively supported in Javascript and
is often used for sending data between a client and server but is also
widely supported by many programming languages and systems, making it an
ideal language agnostic method of transferring data. In Python the
json module provides loads and dumps methods for converting
between JSON and Python dictionaries.
Flask
Flask is a web micro-framework written in Python. It is not installed by
default so you need to install it with pip install flask. It provides
a way to respond to requests using routes and send responses. It makes
uses of Jinja for templates and has extensions for interfacing with
databases, authentication and forms. A basic Flask app is shown below:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Website is working"
This app can be run with flask run from the command line.
The first line imports Flask and the second creates the Flask app. The
__name__ helps Flask work out which folder it's in.
The @app.route is called a decorator and it says that the function
defined below is how Flask should respond to a request for /, which is
the root of your website. The function index is called whenever this
request is made and the message it returns is sent as a response.
Basic forms
Suppose we have the form from the last section in
a file called index.html in a directory called templates and the
following Python file in the current directory:
from flask import Flask, request, render_template, redirect
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
@app.route("/login", methods = ["POST"])
def login():
print(request.form["username"] + "\n" + request.form["password"])
return redirect("/")
Flask can get request parameters using the request object. You have to
import this from flask. request.form allows you to access form
parameters, request.method gives you the request method (usually GET
or POST) and request.args.get(...) allows you to access the GET
parameters. In the example above the username and password sent will be
printed out. The "username" and "password" correspond to the name
attributes of the inputs in the form.
Security
Passwords can be hashed using the Werkzeug security module. Generate a
hash using
generate_password_hash(password) and check it using
check_password_hash(hash, password).
Jinja
Flask templates use the Jinja template engine to produce HTML
dynamically. Templates are stored in the templates directory. A Jinja
template is just a normal HTML file but some parts are placeholders
instead.
Example template:
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
{% if weekday %}
<p>It's {{ dayOfWeek }}. You get 10% off!</p>
{% else %}
<p>Come back any time in the week to get 10% off.</p>
{% endif %}
</body>
</html>
The double braces are placeholders for expressions and the lines
beginning with % are statements. For example, title will be replaced
with the value of the variable title, which is passed to the template
using render_template.
The if statement causes the template to render differently depending on
whether it's a weekday or not. There are also % for % statements for
iteration.
This template would be returned by a Flask route using
return render_template("index.html", title = "Special offer", weekday = True, dayOfWeek = "Wednesday")
It is also possible to include files in other templates using
% include:
<main>
...
</main>
{% include "footer.html" %}
</body>