Creating RESTful Web APIs using Flask and Python
Programming
Creating RESTful Web APIs using Flask and Python
A Comprehensive Guide for building Web APIs with Flask
Flask is a widely used micro web framework for creating APIs in Python. It is a simple yet powerful web framework which is designed to get started quick and easy, with the ability to scale up to complex applications.
From the documentation,
“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.
Installation
Install Flask using pip
pip install Flask
Minimal Flask App
from flask import Flaskapp = Flask(__name__)@app.route('/hello/', methods=['GET', 'POST'])
def welcome():
return "Hello World!"if __name__ == '__main__':
app.run(host='0.0.0.0', port=105)
Save this file as app.py
(or any other filename you want) and go to terminal and type python app.py
(i.e. python <filename>.py
)
You should see something like this:
* Running on http://0.0.0.0:105/ (Press CTRL+C to quit)
Launch any web browser and go to http://localhost:105/hello/
to see the app in action.
Now, let’s understand the working of the code line-by-line:
from flask import Flask
→ Import the Flask class
app = Flask(__name__)
→ Create an instance of the class
@app.route('/hello/', methods=['GET', 'POST'])
→ We use the route()
decorator to tell Flask what URL should trigger the function. methods
specify which HTTP methods are allowed. The default is ['GET']
if __name__ == '__main__'
→ __name__
is a special variable in Python which takes the value of the script
name. This line ensures that our Flask app runs only when it is executed
in the main file and not when it is imported in some other file
app.run(host='0.0.0.0', port=105)
→ Run the Flask application
host
specifies the server on which we want our flask application to run. The default value for host
is localhost
or 127.0.0.1
0.0.0.0
means “all IPv4 addresses on the local machine”. This ensures that the server will be reachable from all addresses.
The default port
value is 5000
and you can set the parameterport
to use the port number of your choice.
Variable Rules
You can add variable sections to a URL by using <variable_name>
. The function receives the variable as a keyword argument.
from flask import Flask
app = Flask(__name__)@app.route('/<int:number>/')
def incrementer(number):
return "Incremented number is " + str(number+1)@app.route('/<string:name>/')
def hello(name):
return "Hello " + nameapp.run()
Run the above code to start the Flask application.
Open the browser and go to http://localhost:5000/Jimit
, you will see the output as Hello Jimit
and when you go to http://localhost:5000/10
the output will be Incremented number is 11
.
Return JSON Serializable Output
The return value from a function in a Flask app should be JSON serializable. You can use jsonify
to make your output JSON serializable. This function wraps json.dumps()
to turn the JSON output into a Response object with application/json mime-type.
Example 1:
This example shows how to use jsonify
for dictionary objects:
from flask import jsonify@app.route('/person/')
def hello():
return jsonify({'name':'Jimit',
'address':'India'})
This will send a JSON response like this:
{
"address": "India",
"name": "Jimit"
}
Example 2:
You can also use jsonify
to automatically serialize lists and tuples to JSON Response.
from flask import jsonify@app.route('/numbers/')
def print_list():
return jsonify(list(range(5)))
This will produce output as:
[
0,
1,
2,
3,
4
]
Redirection Behaviour
@app.route('/home/')
def home():
return "Home page"@app.route('/contact')
def contact():
return "Contact page"
In the above example, the URL for the home
endpoint has a trailing slash whereas the URL for the contact
endpoint is missing the trailing slash.
This results in two different behaviours:
- For the
home
endpoint, if you access the URL without the trailing slash, then Flask redirects you to the URL with the trailing slash. - For the
contact
endpoint, if you access the URL with the trailing slash, then it will result in status 404 Not Found.
Return Status Code
You can return the status code along with the Response by specifying the status code as follows:
@app.route('/teapot/')
def teapot():
return "Would you like some tea?", 418
The response to this URL will be Would you like some tea?
with 418
as the status code instead of the usual 200
.
Before Request
You can specify a function which should always execute before the request is processed by using app.before_request
decorator.
@app.before_request
def before():
print("This is executed BEFORE each request.")
@app.route('/hello/')
def hello():
return "Hello World!"
For this example, the statement This is executed BEFORE each request.
will be printed on the server first and then the function for the hello
endpoint will be executed. This is particularly useful when you want to log the requests for monitoring purposes.
Accessing Request Data
To access the request data, use the following
from flask import request
You can use the following attributes to fetch the data sent with the request:
request.data
→ Access incoming request data as string
request.args
→ Access the parsed URL parameters. Returns ImmutableMultiDict
request.form
→ Access the form parameters. Return ImmutableMultiDict
request.values
→ Returns CombinedMultiDict
which combines args
and form
request.json
→ Returns parsed JSON data if mimetype is application/json
request.files
→ Returns MultiDict
object which contains all uploaded files. Each key is the name of the file and value is the FileStorage
object.
request.authorization
→ Returns an object of Authorization
class .It represents an Authorization header sent by the client.
app.run() parameters
app.run()
runs the application on the server. There are various parameters which you can use with app.run()
in addition to host
and port
Some of them are:
debug
→ If the debug
parameter is set to True
then the server will automatically reload on code changes and show an
interactive debugger in case of unhandled exceptions. The default is False
use_reloader
→ When use_reloader
is set to True
, the server will automatically restart when code changes. Defaults to False
threaded
→ When threaded
is set to True
, the process will handle each request in a separate thread. Default is False
ssl_context
→ SSL Context for the connection. Expects ssl.SSLContext
, a tuple in the form (cert_file, pkey_file)
, or the string 'adhoc'
if the server should automatically create the context. Default is None
i.e. SSL is disabled.
This is used when we want to host the Flask application on HTTPS instead of HTTP.
Blueprints
Blueprints allow us to separate various endpoints into subdomains.
home.py
from flask import Blueprinthome_bp = Blueprint('home', __name__)@home_bp.route('/hello/')
def hello():
return "Hello from Home Page"
contact.py
from flask import Blueprintcontact_bp = Blueprint('contact', __name__)@contact_bp.route('/hello/')
def hello():
return "Hello from Contact Page"
app.py
from flask import Flaskfrom home import home_bp
from contact import contact_bpapp = Flask(__name__)app.register_blueprint(home_bp, url_prefix='/home')
app.register_blueprint(contact_bp, url_prefix='/contact')app.run()
Note that in both the blueprints, the /hello/
route is calling the hello
function.
When you go to http://localhost:5000/home/hello
, the output will be Hello from Home Page
and when you visit http://localhost:5000/contact/hello
, the output will be Hello from Contact Page
Logging
You can use the following methods to log statements in a Flask Application
app.logger.debug('This is a DEBUG message')
app.logger.info('This is an INFO message')
app.logger.warning('This is a WARNING message')
app.logger.error('This is an ERROR message')
References
Resources
All the code snippets of this article are available on my GitHub Page.
Suggested Reading
Building Python APIs with Flask, Flask-RESTPlus and Swagger UI
Let’s Connect
LinkedIn: https://www.linkedin.com/in/jimit105/
GitHub: https://github.com/jimit105
Twitter: https://twitter.com/jimit105
Author - Jimit Dholakia
References - https://towardsdatascience.com
Comments
Post a Comment