Please click here to check my first part [part-1] of this blog
In previous section we have discussed about
- About web Framework
- About Flask framework
- HTTP methods used in Flask framework
- A minimal Flask application
- A new approach using OOP's with Flask Framework
Now we are going to discuss further deep going into the concept
In the previous part we have discussed about the Flask framework which can be worked using classes and object, but not quitely.
We have just created a FlaskAppWrapper
class which takes the flask app and allows us to add the endpoints and routing.
The FlaskAppWrapper
class make sure functionality of add_endpoint
method which is used to routing the method with appropriate endpoint given as an arguments passed to it.
In this section we are going to discuss about
- Routing
- Dynamic Routing
- EndpointHandler class
- How EndpointHandler class helps in routing
Routing
App routing is used to map the specific URL with the associated function
that is intended to perform some task.
The associated function is called handler
in our case.
The add_endpoint
method add the new endpoint for a given handler
should be a callable function executed when you invoke the url with a given endpoint should be callable type rather you pass any arguments to it or not uses add_url_rule(<url_rule>, <endpoint>, <view_function>)
which we have discussed before in the previous section which is used to perform routing for flask application.
Here,
-
<url_rule>
is the endpoint -
<endpoint>
is the endpoint name which rather is the name of the handler and -
<view_function>
is the associated function, rather say handler which is executed when we call the URL with the registered endpoint.
If you pass any arguments to that callable handler, you have the request.view_args
method which should be imported from the flask
module which will will store the arguments.
Dynamic routing
Here we use a concept of Dynamic routing
. Flask provides the functionality of the dynamic routing.
It is the process of getting dynamic data(variable names) in the URL and then using it.
In Flask you can have use following converters to convert dynamic input from the URL.
- string
- int
- float
- path ( It is simple a string but also accepts shashles in the URL)
- uuid
Dynamic URL's
in Flask play an important role in the ability to create unique URL's that aren't hard-coded into our application.
EndpointHandler class
To pass the arguments, we have to create another class name EndpointHandler
which is responsible for executing the handler
according to the endpoint.
class EndpointHandler(object):
def __init__(self, action):
self.action = action
def __call__(self, *args, **kwargs):
response = self.action(*args, **kwargs)
return response
Let's save in handler.py
file.
In the above code we have created EndpointHandler
class where the instance of that class is callable. Callable in the sense that instance of the class act's similar to the function. The __call__
method makes the instance callable and executes what inside the __call__
method.
Here in the class EndpointHandler
takes the action
which will be the any function or any method from class.
Let's test with any built-in function in python.
There are so many built-in function in python such as print
, list
, len
etc..
Let's try with print
as an argument of an instance of the class.
handler = EndpointHandler(print)
handler("Hello world")
The output will be like this
C:\>python handler.py
Hello world
That means print
function is an action of handler
which is an instance of a class and it is callable and prints anything we pass as an arguments. That means that handler
instance has the functionality of the print
function and acts as the same function we passed into it.
We have to check whether it works on user defined function
.
Let's take an example of the function called action shown below.
def action(a,b):
"""
This action is an example function which takes the two parameter a and b of Integer type and returns the sum of a and b
"""
return a + b
Now Let's make an instance of the class name handler
and pass the action
function as arguments in class.
handler = EndpointHandler(action)
result = handler(5, 6)
print(result)
You will get the output as the sum of 5
and 6
which is 11
. That means we have concluded that the EndpointHandler
class is the callable class which takes the associative function
which is stored in the action
parameter, performs the same functionality with the action
.
How EndpointHandler class
will help in Routing
in flask
?
We have the EndpointHandler
class which we have discussed in the previous part of the blog is shown below, the only change is we are going to pass the endpoint of EndpointHandler
class FlaskAppWrapper(object):
def __init__(self, app, **configs):
self.app = app
self.configs(**configs)
def configs(self, **configs):
for config, value in configs:
self.app.config[config.upper()] = value
def add_endpoint(self, endpoint=None, endpoint_name=None, handler=None, methods=['GET'], *args, **kwargs):
self.app.add_url_rule(endpoint, endpoint_name, EndpointHandler(handler), methods=methods, *args, **kwargs)
def run(self, **kwargs):
self.app.run(**kwargs)
There are some changes should be done in EndpointHandler
class when you are working in flask
shown below.
from flask import request, make_response
class EndpointHandler(object):
def __init__(self, action):
self.action = action
def __call__(self, *args, **kwargs):
response = self.action(*args, **request.view_args)
return make_response(response)
where,
request.view_args
A dict of view arguments that matched the request. If an exception happened when matching, this will beNone
.make_response
Convert the return value from a view function to an instance of response_class.
Now, We have to test our FlaskAppWrapper
with a new function called action
and we are going to pass name
argument to it
def action(name):
"""
This function takes `name` argument and returns `Hello name`.
"""
return "Hello " + name
Now we are going to define the flask app and we are going to register the action
function.
flask_app = Flask(__name__)
app = FlaskAppWrapper(flask_app)
# register the action function to app
app.add_endpoint('/action/<string:name>', 'action', action)
if __name__ == '__main__':
app.run(debug=True)
The whole code looks like
from flask import Flask, request, make_response
class EndpointHandler(object):
def __init__(self, action):
self.action = action
def __call__(self, *args, **kwargs):
response = self.action(*args, **request.view_args)
return make_response(response)
class FlaskAppWrapper(object):
def __init__(self, app, **configs):
self.app = app
self.configs(**configs)
def configs(self, **configs):
for config, value in configs:
self.app.config[config.upper()] = value
def add_endpoint(self, endpoint=None, endpoint_name=None, handler=None, methods=['GET'], *args, **kwargs):
self.app.add_url_rule(endpoint, endpoint_name, EndpointHandler(handler), methods=methods, *args, **kwargs)
def run(self, **kwargs):
self.app.run(**kwargs)
def action(name):
"""
This function takes `name` argument and returns `Hello <name>`.
"""
return "Hello " + name
flask_app = Flask(__name__)
app = FlaskAppWrapper(flask_app)
# register the action function to app
app.add_endpoint('/action/<string:name>', 'action', action)
if __name__ == '__main__':
app.run(debug=True)
The code above shown works like this
Firstly, I have imported some requirements from
Flask
framework.We have created the
EndpointHandler
class which is responsible for managing to pass the extra arguments or parameters to be passed when anaction
is invoked.Then we have worked with the
FlaskAppWrapper
class and we have discussed about it in the previous part and we made some changes which is menctioned in the above discussion.To test the
FlaskAppWrapper
class we have defined theaction
function which takes thename
as the parameter and returns the string asHello <name>
.We have defined the
flask_app
as the instance of theFlask
class and thisflask_app
instance is given to ourFlaskAppWrapper
class and this instance is stored inapp
.We have registered the
action
function to theapp
instance using theadd_endpoint
method by giving the appropriateendpoint
to theaction
function. In this case/action/<string:name>
is the endpoint for theaction
function that means, when we invoked the Flask app url with the endpoint above executes theaction
function which we have registered and we are going to see in the output section.We are going to run the file using
app.run()
method and we see the output
We save the above code as example6.py
and run using the command
C://> python example6.py
And then we are going to click on the url shown below.
We are heading over to http://127.0.0.1:5000/action/Tejas in any search engines (I'm using Google) and we get the output as shown below
We have observed that after heading to the url above, You get the output as Hello Tejas
and Tejas
is the name I have passed over the action
function.
We will check with other name say Subash
.
Head over to http://127.0.0.1:5000/action/Subash the output is as shown below
A broad example
Now we will test our application by adding many actions to our FlaskAppWrapper
class.
The whole code looks like
from flask import Flask, request, make_response
class EndpointHandler(object):
def __init__(self, action):
self.action = action
def __call__(self, *args, **kwargs):
response = self.action(*args, **request.view_args)
return make_response(response)
class FlaskAppWrapper(object):
def __init__(self, app, **configs):
self.app = app
self.configs(**configs)
def configs(self, **configs):
for config, value in configs:
self.app.config[config.upper()] = value
def add_endpoint(self, endpoint=None, endpoint_name=None, handler=None, methods=['GET'], *args, **kwargs):
self.app.add_url_rule(endpoint, endpoint_name, EndpointHandler(handler), methods=methods, *args, **kwargs)
def run(self, **kwargs):
self.app.run(**kwargs)
def action1(name):
"""
This function takes `name` argument and returns `Hello name`.
"""
return "Hello " + name
def action2():
"""
This function returns "Action2 invoked"
"""
return "Action2 invoked"
def action3(number):
"""
This function returns the cube of the number
"""
return "Cube of {0} is {1}".format(number, number**3)
flask_app = Flask(__name__)
app = FlaskAppWrapper(flask_app)
# register all action functions to app
app.add_endpoint('/action1/<string:name>', 'action1', action1)
app.add_endpoint('/action2/', 'action2', action2)
app.add_endpoint('/action3/<int:number>', 'action3', action3)
if __name__ == '__main__':
app.run(debug=True)
From above code, we have registered the 3 action functions to our app
.
action1
takes thename
parameter from the endpoint and returnsHello <name>
.action2
returnsAction2 invoked
.action3
takes thenumber
parameter from the endpoint and returns the cube of the number.
After running the above code we get the output shown below
- Heading over http://127.0.0.1:5000/action1/Tejas We get the output as shown below
- Heading over http://127.0.0.1:5000/action2/ we get the output as
- Heading over http://127.0.0.1:5000/action3/10 we get the output as
Same url, different endpoints and different functions are invoked and executed.
We are going to declare that any number of actions can be registered in our app
and I conclude that the FlaskAppWrapper
class works as good as the Flask application and this is the approach I have researched.
Summary
We have discussed in this part about
- Routing and Dynamic Routing in Flask
- Handling the flask endpoint using
EndpointHandler
class - Discussed and made some changes in the
FlaskAppWrapper
class. - Tested the updated code with the concept of
Dynamic routing
.
Top comments (0)