This workshop is a basic introduction to Flask, a popular webframework for Python. Flask allows you to build Web applications in a simple way. An alternate is Django, which follows a batteries-included approach. Flask follows the opposite approach.
Flask can be used to build many things, from complex web applications to IoT projects such as the trainer's Speaking Bookshelf.
Vinay Keerthi is a self-taught programmer who has been meddling with, and breaking computers since he was 14. His first computer was an Atari 600XL, which he used to program in BASIC. His programming interests include Python, MicroPython and Rust. He is currently writing a book on MicroPython which will be published by Apress around December 2020.
- Basics
- Decorators and Getting Started
- Add HTML to the content of the home page.
- Move HTML to a template page.
- Add a second page.
- Modularize both pages.
- Routes
- GET and queries
- Using Postman
- POST
- PUT, DELETE
- Debugging with VS Code.
- Adding a
launch.json
file
- Adding a
- Adding a Database
- flask_sqlalchemy: db.Model example table
- Adding a second table.
- Flask shell
- Using flask-shell to debug.
- Adding values to the database.
- Querying values
- Removing values from the database.
- Front-End
- Adding Bootstrap CSS.
- Adding a simple template.
- A simple form.
- Flask Modularization
- moving files.
- blueprints
- logging to a file
- Creating an Application
- Designing the API with Stoplight Studio
- Adding helper command to
flask
CLI to load data. - Add a flask extension:
flask-admin
- Home page
- Movie display page.
- [BONUS] Dockerfile!
Make sure you install Python 3.6 or greater. Use Anaconda or Miniconda if you don't know how.
Then follow these steps.
# Windows users, make sure you have git installed.
git clone https://github.com/bangpypers/23-05-2020-flask-workshop.git
cd 23-05-2020-flask-workshop
python -m venv env
source env/bin/activate
# env\Scripts\activate.bat for Windows. You shouldn't prefix this with `source`
pip install -r requirements.txt
This is enough to get you setup for the workshop.
This repository will always have a master
branch that is latest with the
final state of the application. However, that will be daunting for anyone to
read through. So, please make continuous use of the tags that I have put together
to rewind to older states of the application.
To list all tags: git tag -l -n9
To rewind the app to a specific tag, use the following command:
git checkout v0.1
You can feel free to make changes or play around with the application.
Just checkout a later commit:
git checkout v0.9
The decimal portion of the application version will correspond to the agenda.
From v0.7.x, the app should be run using the wsgi.py
file. WSGI stands for
Web Server Gateway Interface. Flask apps should not be run in production
using flask run
. And they should not rest in one file. A modular approach
ensures that all the modules are easy to debug, and the history is isolated to
separate files.
export FLASK_APP=wsgi.py
export FLASK_DEBUG=1
# windows users,
# use SET instead of EXPORT
flask run
Open this page on your browser.
To check out the search URL, try this page.
You can use the http
command to test the API.
http http://localhost:5000/json-example
Note: Ensure you have installed httpie using:
pip install -r requirements.txt
The output I get is:
HTTP/1.0 200 OK
Content-Length: 96
Content-Type: application/json
Date: Fri, 22 May 2020 17:26:39 GMT
Server: Werkzeug/1.0.1 Python/3.8.3
{
"animal": "Cat",
"name": "John Doe",
"place": "Amsterdam",
"thing": "Volleyball"
}
Sometimes it is easier to use a GUI to check your API. Postman is one such app for this.
The easiest way to read the final application is from the app.py
file. The
function create_app
is your entrypoint into the application.
This section explains a bit about routes and queries.
When you visit a URL you are probably used to seeing the https://www.google.com/
portion of the website. Everything following the first /
after the .com
(this could be .org
or .in
or anything else) is the route for the page.
For your site, when you visit http://localhost/
, the default route is the
index. This is /
. We added a /about
route, mapping a page to it.
If you noticed in the first example, we don't need to return html content for a request. We can return anything, really.
The default type of request is GET. This can be interpreted literally. Get what I asked for.
http://localhost:5000/
means get the index route of http://localhost.
http://localhost:5000/about
means get the about route of http://localhost.
A POST is a different type of request. When a client (this is a browser or a script such as what I will show you now) sends a POST, it is usually from an internal function and never from the URL in a browser. The address bar always performs a GET.
To try out our sample API for POST:
http POST :5000/post-example
# httpie allows you to just skip the http://localhost part of the URL nicely.
Output:
HTTP/1.0 200 OK
Content-Length: 107
Content-Type: application/json
Date: Fri, 22 May 2020 17:51:29 GMT
Server: Werkzeug/1.0.1 Python/3.8.3
{
"null_value": null,
"some_number": 34298,
"string_sample": "flask is fun!",
"success": true
}
In postman:
You can have combined routes by using the methods
argument to @app.route
.
This enables you to use request.method
to change the behaviour of your
API based on how users are using it.
Test it out.
http GET :5000/combined-example -f
Output:
HTTP/1.0 200 OK
Content-Length: 82
Content-Type: application/json
Date: Fri, 22 May 2020 18:13:15 GMT
Server: Werkzeug/1.0.1 Python/3.8.3
{
"message": "You got what you asked for.",
"number": 1,
"sucess": true
}
http POST :5000/combined-example id=10 -f
Output:
HTTP/1.0 200 OK
Content-Length: 91
Content-Type: application/json
Date: Fri, 22 May 2020 18:13:39 GMT
Server: Werkzeug/1.0.1 Python/3.8.3
{
"id": "10",
"message": "You posted something",
"number": 2,
"success": true
}
http PUT :5000/combined-example id=123 -f
Output:
HTTP/1.0 200 OK
Content-Length: 93
Content-Type: application/json
Date: Fri, 22 May 2020 18:14:27 GMT
Server: Werkzeug/1.0.1 Python/3.8.3
{
"id": "123",
"message": "You put something here",
"number": 2,
"success": true
}
In Postman:
http DELETE :5000/combined-example id=92 -f
Output:
HTTP/1.0 200 OK
Content-Length: 92
Content-Type: application/json
Date: Fri, 22 May 2020 18:15:25 GMT
Server: Werkzeug/1.0.1 Python/3.8.3
{
"id": "92",
"message": "You deleted something",
"number": 2,
"success": true
}
Routes sometimes have meaningful data in them. A good analogy is to think of a route as a postal address.
In API terms:
charlie
road #42
ChocolateFactory
could become:
/ChocolateFactory/road/42/charlie
Note that this does not follow any sort of standard on how APIs should look, but this is quite feasible.
A query is the second easiest way to pass data to a route. You have used
queries millions of times without realizing it. Google uses a query to
lead you to the search results: https://www.google.com/search?q=how+do+I+use+google
.
the ?q=...
portion is just a query where the API gets the values after ?
as an accessible string.
The Official docs for VS Code cover how to use the debugger nicely.
An application most often needs a database. Adding one with flask_sqlalchemy
is simple.
Once you make the changes that are in v0.4.2, make sure to run the following:
export FLASK_APP=app.py
export FLASK_DEBUG=1
flask shell
>>> from app import db
>>> db.create_all()
# This creates the database.
In the flask shell:
from app import Movie, db
movie = Movie(title="The Mask")
db.session.add(movie)
db.session.commit()
from app import Movie
movie = Movie.query.filter(Movie.title.like("%Mask%")).first()
print(movie)
from app import Movie, db
movie = Movie.query.filter(Movie.title.like("%Mask%")).first()
print(movie)
db.session.delete(movie)
db.session.commit()
If you are new to SQL, I strongly recommend reading the first few sections
of the postgresql
documentation, linked in the resources section below.
A flask app becomes more complex as it grows. This is when you should break it up so that your logic becomes easier to debug.
The v0.7.x
tags show how to split the previous application into several
modules.
In Flask, blueprints are a modular way of seggregating the API. A blueprint behaves like a regular flask app, but it does not run until it is attached to a flask application. The reason we use a blueprint is so that if the app has to be used in another application, then it can be easily imported there and used.
Check workshop/blueprints
for more info.
Stoplight studio is a great way to chart out an API before you begin work on it.
You can design the API and then export a swagger file that tells other developers how you wanted to design the API at a later point.
Here are some screenshots.
Take a look at the swagger.yml
file to know more.
You can add and create your own flask commands. Check out app.py and the
section using app.cli
for more. See tag v0.8.2.
As a bonus I have included a dockerfile for this application.
To build:
docker build -t workshop .
To run:
docker run --rm --name workshop -p 5000:5000 workshop
- Flask Website
- Flask Mega-tutorial
- Explore Flask
- Git Tutorial videos Pro-Git Book
- Automate the Boring Stuff with Python
- Flask-SQLAlchemy
- SQL Tutorial on Postgres Documentation
- Postman
- StopLight API Design Tool
- httpie Commandline tool
- Real Python Decorators Tutorial
- Real Python Virtualenv Primer
Vinay goes by @stonecharioteer everywhere. Twitter is an easy way to reach him, or reddit, if you are brave enough.
As requested by the audience, here are a few photos and details.
Vinay has been using Linux Mint for over 14 years now, and he swears by it. His current window manager is Cinnamon, but he mostly lives in the terminal. He uses ZSH, and this is the gist containing his dotfiles, including his VSCode settings.json.
He loves assembling Mechanical Keyboards. He owns a Daisy 40%, a hand-soldered Lily58 Split and a hand-soldered Corne Keyboard. His current favourite is undoubtedly the Corne.