It's easy to creat an api or restful api with Flask and Flask-RESTful extension. But what's happening under the hood when executing the code?
In this blog, we will dive into the source code of Flask framework and its extension Flask-RESTful, and understand the code deeply.
Flask API
We can create an api with Flask quickly and easily.
1 | from flask import Flask, jsonify, request, render_template |
We use decorator app.route()
to create endpoints. It's like a magic —— we provide an URL rule and/or some methods to the decorator, then we can call the corresponding function by typing URL in our browser or Postman.
But it's not a magic. There is a function called route
in Flask
class.
1 | # app.py |
1 | # endpoint |
The app.route('/')
will call this higher-order function route
, where parameter self
is app
and rule
is '/'
, then the function decorator
will be returned.
When applying decorator
to our user-defined function, such as index
, we can see this function will add the previous given url rule, i.e. '/'
, to the app. So when we type the url '/'
, the Flask app will help us trigger the corresponding function index
, and returns Hello World
.
Pluggable Views
Introduction
A view function, or view in short, is just a Python function that takes a web request and returns a web response.
In the last section, we use decorators to register view functions, and use them to deal with requests. However, this way is not generic and not flexible if we want to apply other models or templates.
1 | # view function is not generic and flexible |
This is where pluggable view comes in.
Flask 0.7 introduces pluggable views inspired by the generic view from Django. The pluggable views are based on classes instead of functions. We can use customized class view to deal with requests.
See an example. With the following code, we can type a specific url to let Flask app trigger the corresponding function.
1 | from flask.views import View |
In this example, we define some pluggable views instead of view functions, then use add_url_rule()
method to register a rule for routing. You should notice that, although we also use add_url_rule()
here, there is a slight difference between this example and the previous example.
1 | # Comparasion |
Although we use pluggable view in the latter case, we still need to convert it into view function when register URL rule for app. The as_view
class method will convert that pluggable view class into an actual view function. The string you passed is the name of the endpoint that view will then have. Whenever a request is dispatched, a new instance of the class is created based on url rule. Then, the instance's dispatch_request() method will be called.
MethodView
For RESTful API, it is helpful to execute different function for each HTTP method. This is where flask.views.MethodView
comes in.
MethodView is also a class-based pluggable view that dispatches request methods to the corresponding class methods. It has already implemented dispatch_request
method, so you don't have to implement it by yourself.
1 | from flask.views import MethodView |
Summary
Each URL rule is corresponding to a view. The view is callable and can deal with request and return a response. When a Flask api receives a request, it has two ways to deal with it. One is by using "FUNCTION-BASED VIEW" directly, while another way is using "CLASS-BASED VIEW".
- function-based view
- use "route(url_rule, methods)" decorator to register view function.
- the route decorator will add url-rule to the app by using "add_url_rule(rule, endpoint, view_func)" function
- this way is suitable for simple requests
- class-based view
- customized-class view must inherit "View" class or "MethodView" class, and must override dispatch_request method (MethodView has already override the dispatch_request method)
- use "add_url_ruler(rule, endpoint, view_func)" to add url rule to the app
- use class method "as_view()" to convert a class into an actual view function
- whenever a request is dispatched, create a new instance based on url rule, then call its dispatch_request method
Flask-RESTful API
Now, let's use Flask and its extension flask-restful
to build a RESTful API.
Resource is the core when designing a RESTful API. We make resources as the center to design different url rules, and define different HTTP methods for resource to manipulate it.
To do this,
1️⃣ first we should define the resources that our api can work with.
2️⃣ Then, define different methods that the resource should support.
3️⃣ Finally, add the defined resources to our api.
1 | """ restful api demo """ |
Let's see the source code.
1 | class Api(object): |
Api
is the main entry point for the application. You need to initialize it with a Flask Application.Resource
represents an abstract RESTful resource. Concrete resources should extend from this class and expose methods for each supported HTTP method. If a resource is invoked with an unsupported HTTP method, the API will return a response with status 405 Method Not Allowed. Otherwise, the appropriate method is called, and all arguments from the url rule which is used when adding resource to an api instance will be passed to the method.
We use a Flask instance app
to initialize Api
class and get an instance api
, so api.app = app
. When executing api.add_resource(resource, urls)
(Line 19 in restful demo) , since api.app
is not None, so a pluggable view will be registered by calling _register_view
method. Here, the resource
is the Student
class. Finally, the url rule will be added to the app.
Until now, I think you should understand every line of our code when building a simple Flask API or Flask RESTful API. If you have question or suggestion, please leave me a message.
Thank you so much, and see you later. 💝