Before we can start a Flask server, we need to understand what Flask is. Flask is a micro-framework for the web. A framework is a collection of code (software) that can be used to build web applications. As a developer, you don't need to start from scratch (all the time) when you can make good use of tools designed to help you with your projects.
The 'micro' in Flask may be a bit misleading, but the good folks at Flask have taken their time to clarify this:
“Micro” does not mean that your whole web application has to fit into a single Python file (although it certainly can), nor does it mean that Flask is lacking in functionality. The “micro” in microframework means Flask aims to keep the core simple but extensible. Flask won’t make many decisions for you, such as what database to use. Those decisions that it does make, such as what templating engine to use, are easy to change. Everything else is up to you, so that Flask can be everything you need and nothing you don’t.
We need to create an application before we can start a Flask server. The application is the main object that holds all the information about what we want to build.
You can browse the completed project on the GitHub repository Start a flask server.
Principally, I will employ the concept of seperation of concerns when building our flask application. What this principle means is that we will categories our application into modules. We will have several modules that will be responsible for different parts of our application. For example, we will have a module that will be responsible for the routes, and another module that will be responsible for the errors.
Using the command line, let us create this application structure:
project_name
| --- test.py
| --- config.py
| --- requirements.txt
| --- .gitignore
| --- .flaskenv
| --- app/
| --- __init__.py
| --- routes.py
| --- errors.py
| --- templates/
| --- base.html
| --- index.html
| --- static/
| --- css/
| --- main.css
| --- js/
| --- img/
mkdir project_name # Create the project directory
cd project_name # Change to the project directory
touch requirements.txt config.py # Create all the files in the top-level directory
mkdir app # Create the app sub directory in the current directory
touch app/__init__.py app/routes.py app/errors.py # Create the files in the app directory
# Create the templates and static sub-directories and their contents
The .gitignore
file is used to ignore the files that we don't want to be tracked by git
. Find out what Python files you wont need to be tracked by git
by looking at the gitignore file.
During the development of this simple Flask application, we will need to install a few packages. We will create and activate a virtual environment. Virtual environments help isolate the needs of your application from that of your system. It also helps isolate one project's needs from another.
mkvirtualenv flask_project # Create a virtual environment
# Output:
(flask_project) $
I am using the virtual environment flask_project
to develop this application. The command mkvirtualenv
is used to both create and activate a virtual environment for me. All the project's dependencies will be installed in this virtual environment.
If you are not aware of what the virtualenvwrapper
is and would like to use it during your development, you can find out more about it here.
One package will definitely need to install is Flask. We will do so using the pip
package manager in our terminal:
(flask_project) $ pip install flask
Within our __init__.py
file, we will create an instance of the Flask application. We will also import the Flask
class from the flask
module.
__init__.py: Create application instance
from flask import Flask
app = Flask(__name__)
from app import routes, errors
Routes direct us to a resource we may request. Each route is built using a view functin. The view function is responsible for returning the response to the request. For now, let us simply return a string, the classic 'Hello, World'.
route.py: Create routes
from app import app
@app.route('/')
@app.route('/index')
def index():
return 'Hello, World!'
When we start our Flask server, we need to tell it what place to start from. This point will act as an entry point to our application.
test.py: Create entry point for the application
from app import app
Flask expects certain environent variables to be set. These run time environment are needed by Flask to run. I created a file called .flaskenv
which we will use to set these environment variables.
.flaskenv: Set environment variables
FLASK_APP=test.py
FLASK_ENV=development
FLASK_DEBUG=1
With the environment variables set, we can now run our application. In the terminal, we can run the following command:
(flask_project) $ flask run
Navigate to the http://127.0.0.1:5000/ in your browser. You should see the following output:
You probably have also noted that in your terminal that there is a soft warning.
This is because when we started our Flask server, the environent variables we set were not read. To ensure that these runtime variable are available on startup, we will need another extension called python-dotenv
. Let us install this extension:
(flask_project) $ pip install python-dotenv
Stop the Flask server by pressing Ctrl + C
in your terminal. Then restart the server using flask run
. All the environment variables should now be set.
Our application is looking so flat at the moment. We can improve its design by installing the flask-bootstrap
package to help us create a beautiful and responsive web application.
(flask_project) $ pip install flask-bootstrap
Instantiate the bootstrap
variable from the flask_bootstrap
package.
from flask import Flask
from flask_bootstrap import Bootstrap # < ---- update
app = Flask(__name__)
boostrap = Bootstrap(app) # < ---- update
from app import routes, errors
Templates are basicaly HTML files which we will use to display content. We will use the jinja2
templating engine to render our templates. At the moment, we have index.html
and base.html
templates. The base.html
template is the parent template for all the other templates (currently we have only index.html
). It will define all the base features of our application.
base.html: Parent template
{% extends 'bootstrap/base.html' %}
<!-- Link all style files here -->
{% block head %}
{{ super() }}
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/main.css') }}">
{% endblock %}
<!-- The title of our application is defined here -->
{% block title %}
{% if title %}
{{ title }} - Flask Server
{% else %}
Welcome to Flask Server
{% endif %}
{% endblock %}
<!-- This is the navbar -->
{% block navbar %}
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href=" # ">Flask Server</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li><a href=" # ">Documentation</a></li>
</ul>
</div>
</div>
</nav>
{% endblock %}
<!-- Contents of all our pages will go here -->
{% block content %}
<div class="container">
{% block app_context %}{% endblock %}
</div>
{% endblock %}
<!-- All scripts will go here -->
{% block scripts %}
{{ super() }}
{% endblock %}
Take your time to go through this template. There are several new things that I have used that you may not be familiar with. One addition that I would like to point out is in the title
block. I have used a conditional statement to find out if the view function that will render index.html
has a title
variable. If it does, then we will use that title. If not, we will use the default title.
Our index.html
template is a child of the base.html
template. We can use the extends
keyword to inherit the parent template.
index.html: Child template
{% extends 'base.html' %}
{% block app_context %}
<div class="row">
<div class="col-md-12">
<h1>Hello, world!</h1>
</div>
</div>
{% endblock %}
Our view function index()
will render the index.html
template. We can use the render_template
function to render a template.
from app import app
from flask import render_template
@app.route('/')
@app.route('/index')
def index():
return render_template('index.html')
# Try to see the differnce between the two lines below
return render_template('index.html')
If you reload your Flask server, you should see the following output:
If you try to access the URL http://127.0.0.1:5000/index1, you will get a 404 Not Found
error. This is because we have not created a view function for the URL /index1
.
To handle this error, I will update our errors
module
errors.py: Error Handling
from app import app, db
from flask import render_template
@app.errorhandler(404)
def not_found(error):
return render_template('404.html'), 404
I have used the app.errorhandler
decorator to register the error handlers. We need to render the 404 and 500 error templates (You can add more). In the terminal, let us run the following command:
(flask_project) $ app/templates/404.html
This will create empty 404.html
and 500.html
templates. We will populate them as follows:
404.html: 404 Not Found
{% extends 'base.html' %}
{% block app_context %}
<div class="row">
<div class="col-md-12">
<h1>Page Not Found</h1>
<p>
<a href="/index">Return to the home page</a>
</p>
</div>
</div>
{% endblock %}
You should have a nicer looking page with a link to the home page.
Once you are done, we can update our requirements.txt
file. This file contains all the dependencies that we have installed. Anyone who wished to install the application will need to install the same dependencies.
(flask_project) $ pip freeze > requirements.txt
The flask run
command is used to start the flask application in a development server. This server provides an interactive debugger and reloads when it notices changes in code. It is intended for local use only since it is not designed to be particularly efficient, stable or secure.
Prior to Flask 1.0 the FLASK_ENV environment variable was not supported and you needed to enable debug mode by exporting FLASK_DEBUG=1. This can still be used to control debug mode, but it is now preferred to set it as an evironment variable.
To stop your flask server, you can hit ctrl + C
. However, when you hit ctrl + Z
, you will notice a traceback when you try restarting your flask server. You will be informed that the address you are trying to connect to is already in use.
* Serving Flask app 'blog.py' (lazy loading)
* Environment: development
* Debug mode: on
Traceback (most recent call last):
# ...
OSError: [Errno 98] Address already in use
To fix it, you need to identify and stop the other program or use the command flask run --port 50001
to pick a different port.
This is a good starting point for your Flask learning. You can build on this project by adding more routes, templates, and view functions. You can even learn how to use webforms and a database with Flask. Things you can do:
- Learn how to work with Flask webforms
- Add a database to your Flask application