Create a virtual environment and install Flask
python -m venv venv
source venv/bin/activate
pip install flask
You can now create a Flask app in a file called app.py
:
from flask import Flask, jsonify
# This creates a Flask application object, which we will use to configure our app.
app = Flask(__name__)
# app.route is a decorator that tells Flask what URL should trigger our function.
# we can use `curl http://localhost:5000/` to see the output
@app.route('/')
def hello_world():
# first parameter is our output, second is the status code (200 = OK)
return jsonify({'message': 'Hello, World!'}), 200
if __name__ == '__main__':
# Specify the port number and set debug=True to enable debugging mode (hot reload)
app.run(port=5000, debug=True)
There are two basic ways we can bind GET and POST requests:
# will answer to GET requests
@app.get('/')
@app.route('/',methods=['GET'])
# will answer to POST requests
@app.port('/')
# will answer to both GET and POST requests
@app.route('/',methods=['GET','POST'])
We can use different methods to handle different requests:
from flask import request
@app.route('/', methods=['GET', 'POST'])
def hello_world():
if request.method == 'GET':
return jsonify({'message': 'Hello, World!'}), 200
elif request.method == 'POST':
return jsonify({'message': 'Hello, World!'}), 201
We can send a JSON body to our server using curl
:
curl -X POST http://localhost:5000/ -d '{"name": "John"}' -H 'Content-Type: application/json'
We can then access the body using request.json
:
@app.post("/input")
def input_method():
body = request.get_json()
if not 'name' in body:
return jsonify({"error": f"You must type in the 'name'"}), 400
return jsonify({"message": f"Hello {body["name"]}!"}), 200
We can create modules (in flask they are called blueprints) to separate our code into different files:
Let's create a blueprint solely for the purpose of handling Rome-related requests:
from flask import Blueprint, jsonify
rome_blueprint = Blueprint("rome", __name__, url_prefix="/rome")
@rome_blueprint.route("/weather")
def weather():
return jsonify({"message": "Hot!"}), 200
We can then load it into our main app:
# register blueprints
app.register_blueprint(rome_blueprint)
# verify the endpoints have been loaded
print(app.url_map)
Print will show us the following:
Map([<Rule '/static/<filename>' (GET, HEAD, OPTIONS) -> static>,
<Rule '/rome/weather' (GET, HEAD, OPTIONS) -> rome.weather>])
As we can see the new blueprint method has been bound to the /rome/weather
endpoint.
Flask by default uses /templates
as the folder for templates. We can use the render_template
method to render a template:
@app.route("/", methods=["GET"])
def hello_world():
return render_template("index.html", date=time.time()), 200
Let's create templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flask App</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<header>
<h1>Welcome to My Flask App</h1>
</header>
<main>
<p>This is the index page.</p>
<p>Today is {{ date }}</p>
</main>
<footer>
<p>© 2023 My Flask App</p>
</footer>
</body>
</html>
Flask uses Jinja2 as the default templating engine. We can use {{ date }}
to access the date
variable we passed to the template.
Flask has two libraries that must be installed in order to create a swagger GUI:
flask-swagger
flask-swagger-ui
We can then use the following snippets (documentation) to create a swagger GUI:
from flask_swagger import swagger
from flask_swagger_ui import get_swaggerui_blueprint
@app.route("/spec")
def spec():
return jsonify(swagger(app))
SWAGGER_URL = '/api/docs'
API_URL = 'http://localhost:5000/spec'
swaggerui_blueprint = get_swaggerui_blueprint(
SWAGGER_URL,
API_URL,
config={
'app_name': "Test application"
})
app.register_blueprint(swaggerui_blueprint)
We can visit http://localhost:5000/api/docs
to see the swagger GUI.