Flask is a simple web framework written in Python.
In this article, we’ll look at how to develop simple Python web apps with Flask.
Accepting JSON Requests
Flask can accept JSON request bodies out of the box.
For example, we can write:
from flask import Flask, jsonify, render_template, request
app = Flask(__name__)
@app.route('/add_numbers', methods=['POST'])
def add_numbers():
content = request.json
a = content['a']
b = content['b']
return jsonify(result=a + b)
to get the request JSON body with the request.json
property.
Get Query Parameters
To get query parameters in our route function, we can use the request.args.get
method:
from flask import Flask, jsonify, render_template, request
app = Flask(__name__)
@app.route('/add_numbers')
def add_numbers():
a = request.args.get('a', 0, type=int)
b = request.args.get('b', 0, type=int)
return jsonify(result=a + b)
We get the value of the a
and b
URL parameters.
The 2nd argument is the default value of each.
And the type
parameter has the data type to return.
So if we go to http://localhost:5000/add_numbers?a=1&b=2, we get:
{
"result": 3
}
as the response.
Custom Error Pages
We can add custom error pages for various kinds of errors.
Common error codes that we run into include:
- 404 — not found
- 403 — accessing a disallowed resource
- 410 — access a deleted item
- 500 — internal server error
We can add error handlers for them by using the @app.errorhandler
decorator.
For example, we can write:
app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
templates/404.html
<p>not found</p>
We pass in 404 ito the @app.errorhandler
decorator to add a route function for the 404 errors.
We just render the template whenever we encounter a 404 error.
Therefore, we’ll see ‘not found’ when we go to a URL that’s not mapped to a route handler.
Returning API Errors as JSON
Also, we can return API errors as JSON.
To do that, we use the jsonify
function.
For instance, we can write:
from flask import Flask, jsonify, abort
app = Flask(__name__)
@app.errorhandler(404)
def resource_not_found(e):
return jsonify(error=str(e)), 404
@app.route("/cheese")
def get_one_cheese():
resource = None
if resource is None:
abort(404, description="Resource not found")
return jsonify(resource)
We have the get_one_cheese
function that returns a 404 response if resource
is None
.
Since it’s none, we see the JSON.
The JSON response is created in the resource_not_found
function, which is the handler for 404 errors.
We call jsonify
in there with the error in the response.
abort
will pass the error into the e
parameter of resource_not_found
.
So, we get:
{
"error": "404 Not Found: Resource not found"
}
returned in the response body when we go to http://localhost:5000/cheese.
MongoDB with MongoEngine
We can manipulate MongoDB databases easily with MongoEngine.
To use it, we install:
pip install flask_mongoengine mongoengine
to install the required libraries.
Then we write:
from flask import Flask, jsonify
from flask_mongoengine import MongoEngine
import mongoengine as me
class Movie(me.Document):
title = me.StringField(required=True)
year = me.IntField()
rated = me.StringField()
director = me.StringField()
actors = me.ListField()
class Imdb(me.EmbeddedDocument):
imdb_id = me.StringField()
rating = me.DecimalField()
votes = me.IntField()
app = Flask(__name__)
app.config['MONGODB_SETTINGS'] = {
"db": "myapp",
}
db = MongoEngine(app)
@app.route('/')
def hello_world():
bttf = Movie(title="Back To The Future", year=1985)
bttf.actors = [
"Michael J. Fox",
"Christopher Lloyd"
]
bttf.imdb = Imdb(imdb_id="tt0088763", rating=8.5)
bttf.save()
return 'movie saved'
@app.route('/query')
def query():
bttf = Movie.objects(title="Back To The Future")
return jsonify(bttf)
to connect to the MongoDB database and do the database queries in our route.
Before we add our routes, we create the classes for the MongDB document schemas.
The classes are subclasses of the me.Document
class.
me.StringField
creates a string field.
me.ListField
creates a list field.
me.DecimalField
creates a floating-point number field.
And me.IntField
creates an integer field.
Then we create our Flask app with the Flask
clas.
And then we add the database connection settings to the MONGO_SETTINGS
config.
Then we invoke the MongoEngine
class with the app
argument to let our routes connect to the database.
Then in hello_world
we create a Movie
document and call save
to save it.
In the query
route, we get the Movie
that are saved with the title
set to 'Back To The Future'
.
Then we can jsonify
on the result to return it as the JSON response.
Conclusion
We can accept a JSON body and query parameters in our requests.
Also, we can create custom error pages and use MongoDB databases with Flask.