Flask Route – How to Perform URL Routing in Flask?

This article will deal with the Flask route to perform URL routing in Flask and then implement it in our flask application. So let’s get started!!
What is URL Routing?
URL routing is used to link a particular function (with the web page content) to its web page URL.
When we hit an endpoint, the web page will display its content, which is the function’s output linked to the URL endpoint using the route.
We can do the URL routing in the following ways:
How to route an URL to a Function
Let’s learn the different ways to setup a Flask route.
1. Using app.route()
Here, the syntax used is as follows:
Therefore an example of Flask application webpage with URL – “localhost:5000/page” will look like:
Note: The function name should be same as the endpoint name.
Run the application:

Blogs
We can also have a URL with a variable endpoint. Such URLs are used for webpages whose functions take in argument from the users.
Consider the function:
Note: Here the non-variable endpoint (blogs) will be the function name and the endpoint variable (id) will be an argument to the function.
Now, as you might have guessed, based on the variable endpoint, the webpage will show different output.

Blog id
2. Using add_url_route() attribute
This function is normally used when we need to route a function externally without using decorators. The syntax :
Therefore consider the below file:
Here the output will be same as before.

Blogs
Similarly, the syntax for variable endpoint is:
There the variable endpoint file syntax will be:
Run the application and note the output:

Blog 1
Here as well the output is same as before.
Conclusion
That’s it for this tutorial, guys! Do try the examples given above yourself for better understanding.
Flask Tutorial: Routes
Modern web apps use a technique named routing. This helps the user remember the URLs. For instance, instead of having /booking.php they see /booking/. Instead of /account.asp?id=1234/ they’d see /account/1234/.
Routes
flask route example
Routes in Flask are mapped to Python functions. You have already created one route, the ‘/‘ route:
The route() decorator, @app.route() , binds a URL to a function.
If you want the route /hello, you can bind it to the hello_world() function like this:
The output of the function hello_world() is shown in your browser.
flask route params
Parameters can be used when creating routes. A parameter can be a string (text) like this: /product/cookie .
That would have this route and function:
So you can pass parameters to your Flask route, can you pass numbers?
The example here creates the route /sale/<transaction_id> , where transaction_id is a number.
flask route multiple arguments
If you want a flask route with multiple parameters that’s possible. For the route /create/<first_name>/<last_name> you can do this:
flask route post
Flask suports HTTP POST requests. If you are unfamiliar with this, I recommend this course: Create apps with Flask.
Routing
Chapter two covers the core functionality of a load balancer: Routing. Although, there are a number of ways to handle routing, we’ll focus only on the following types:
- host-based
- path-based
Why Do We Need Routing?
Routing is a general concept in networking which refers to the path a packet takes to reach a destination. In our case, when we implement routing in a load balancer we’re referring to how HTTP requests reach other collections of servers (or different backend servers). Different routing strategies can be used to control the behavior of the load balancer.
What’s Host-based Routing?
With host-based routing, requests are directed based on the request host header. If the header is not found then the load balancer returns a 404 to the client.

In the above example, the client on the left sends their host header as «www.mango.com» and the load balancer directs them to the mango backend servers. The client on the right, meanwhile, sends «www.notmango.com» and gets a «404 Not Found» back because the load balancer only recognizes «www.mango.com» and «www.apple.com».
So how does one set the host header? There are two ways — explicit and implicit. The explicit way is to simply pass it in your HTTP client.
The implicit way is:
In the implicit case, curl will set the host header for you as it resolves the DNS. For the explicit case we have to pass the header ourselves otherwise we get a redirect 301 code. In the example above, www.google.com is a slightly more complicated case since it has a CDN (Content Distribution Network) in front, so we are not hitting the load balancer directly.
What’s Path-based Routing?
Path-based routing relies on the URI to send the request to the backend servers.
Let’s break down the above:
- https is the protocol
- www.mywebsite.com is the fully qualified domain name (FQDN)
- /apples and /mangoes are the paths
If someone requests the /apples path, we’ll direct the request to the apples backend servers and if someone hits the /mangoes path we’ll direct them to the mangoes backend server.
Path-based routing is a very common pattern for creating microservices to break a large web application into a smaller one. As with the above example, host-based and path-based routing complement each other: Essentially, path-based routing relies on host-based routing.
Implementing Host-Based Routing
Tests
Before we configure the backends up, we need to write some tests:
We removed the test_hello test and added three new tests. Did you notice that the last test also looks at the HTTP status code to confirm that we’re returning the correct status code to the client? Running the above will result in all three tests failing which is what we want.
Multiple Backends
In order to test out the load balancer’s routing functionality, we need to set up multiple servers for each of our hosts. To simplify this, we’ll use both Docker and Docker Compose:
- Docker is a containerization tool designed to simplify the development and deployment of an application.
- Docker-compose is a tool used for defining and running multi-container Docker applications. Each of our backends will run in a separate container.
Let’s start off by creating a very basic Python web server with Flask in a new file called app.py:
The above application takes an environment variable, APP , and simply returns it when the / URL is hit. This allows us to quickly identify the application.
Next, add a Dockerfile:
Build the image:
After pulling the Python 3 base image, we installed Flask, copied app.py over to the container, and ran the app.
We can use this image to spin up multiple containers with Docker Compose:
To spin up the containers, run:
If you get errors in the above step you might have something else running on the 8081, 8082, 9081 and 9082 ports. If that’s the case, change the port numbers to the ones that are free on your operating system.
Test the applications to ensure they work as expected:
Bring the containers down:
Next, to automate spinning the containers up and then tearing them down, add a Makefile to the project root:
Makefiles use tabs rather than spaces. So, if you see Makefile:2: *** missing separator (did you mean TAB instead of 8 spaces?). Stop. when you run make test be sure to convert the indentation in your code editor to tabs for the Makefile.
Also note that we added an || true to the pytest command so that that regardless of the exit code, we’ll ignore it and teardown our containers. We want our tests to not leave anything behind so we can run them again without any manual intervention.
Run make test . You should see a similar output to this:
Implementation
Time to make our tests pass. We’ll us the Requests library to send the HTTP request to the backend server. Start by installing it:
Update the load balancer application:
First, we defined our backend servers for our hosts which are based on the Docker Compose file we generated earlier. Then we fetched the Host header and ran an if condition to check if it matches our criteria. If we got a match, we then chose a backend server at random and sent an HTTP request and returned the HTTP response body and status code back to the client. If we didn’t get any matches, we returned «Not Found» along with a 404 status code.
Let’s run our tests:
They should pass
We have successfully implemented host-based routing. Now let’s do the same for path-based routing.
Implementing Path-Based Routing
Tests
Add the following new tests to test_loadbalancer.py:
We don’t care about the host header in this case.
Implementation
All six tests should now pass:
Conclusion
We’ve gone through what host and path-based routing is, how to write tests for both cases, and how to implement them. Whilst setting up the tests, we used Docker Compose to spin up multiple backend servers for hosts supported by our load balancer.
Navigation and routing
Navigation and routing is an essential feature of Single Page Applications (SPA) which allows organizing application user interface into virtual pages (views) and "navigate" between them while application URL reflects the current state of the app.
For mobile apps navigation and routing serves as a deep linking to specific application parts.
Well, it took more efforts than expected to add navigation and routing into Flet as the implementation is based on Navigator 2.0 Flutter API and required to replace Flet's "Page" abstraction with "Page and Views". Flutter's newer navigation and routing API has substantial improvements such as:
- Programmatic control over history stack.
- An easy way to intercept a call to "Back" button in AppBar.
- Robust synchronization with browser history.
Explore source code of the example above.
Page route
Page route is a portion of application URL after # symbol:

Default application route, if not set in application URL by the user, is / . All routes start with / , for example /store , /authors/1/books/2 .
Application route can be obtained by reading page.route property, for example:
Grab application URL, open a new browser tab, paste the URL, modify its part after # to /test and hit enter. You should see "Initial route: /test".
Every time the route in the URL is changed (by editing the URL or navigating browser history with Back/Forward buttons) Flet calls page.on_route_change event handler:
Now try updating URL hash a few times and then use Back/Forward buttons! You should see a new message added to a page each time the route changes:
Route can be changed programmatically, by updating page.route property:
Click "Go to Store" button and you'll see application URL is changed and a new item is pushed in a browser history. You can use browser "Back" button to navigate to a previous route.
Page views
Flet's Page now is not just a single page, but a container for View layered on top of each other like a sandwich:
A collection of views represents navigator history. Page has page.views property to access views collection.
The last view in the list is the one currently displayed on a page. Views list must have at least one element (root view).
To simulate a transition between pages change page.route and add a new View in the end of page.view list.
Pop the last view from the collection and change route to a "previous" one in page.on_view_pop event handler to go back.
Building views on route change
To build a reliable navigation there must be a single place in the program which builds a list of views depending on the current route. Other words, navigation history stack (represented by the list of views) must be a function of a route.
This place is page.on_route_change event handler.
Let's put everything together into a complete example which allows navigating between two pages:
Try navigating between pages using "Visit Store" and "Go Home" buttons, Back/Forward browser buttons, manually changing route in the URL — it works no matter what! 🙂
To "navigate" between pages we used page.go(route) — a helper method that updates page.route , calls page.on_route_change event handler to update views and finally calls page.update() .
Notice the usage of page.on_view_pop event handler. It fires when the user clicks automatic "Back" button in AppBar control. In the handler we remove the last element from views collection and navigate to view's root "under" it.
Route templates
Flet offers TemplateRoute — an utility class based on repath library which allows matching ExpressJS-like routes and parsing their parameters, for example /account/:account_id/orders/:order_id .
TemplateRoute plays great with route change event:
You can read more about template syntax supported by repath library here.
URL strategy for web
Flet web apps support two ways of configuring URL-based routing:
- Path (default) — paths are read and written without a hash. For example, fletapp.dev/path/to/view .
- Hash — paths are read and written to the hash fragment. For example, fletapp.dev/#/path/to/view .
To change URL strategy use route_url_strategy parameter of flet.app() method, for example:
URL strategy for Flet Server can be configured with FLET_ROUTE_URL_STRATEGY environment variable which could be set to either path (default) or hash .