Understanding URL Routing in Flask

Share this article

Understanding URL Routing in Flask
In this article, we’ll explore URL routing in Flask, discussing its significance in web development and providing insights into how it works.
We’ll delve into various aspects, such as defining routes, handling dynamic URL patterns, supporting different HTTP methods, managing redirects and errors, and following best practices for effective URL routing in Flask.
Table of Contents
  1. Flask and URL Routing
  2. Basic Routing in Flask
  3. Variable Rules
  4. URL Building
  5. HTTP Methods
  6. Redirects and Errors
  7. Best Practices for URL Routing in Flask
  8. Conclusion

Key Takeaways

  1. Understanding URL Routing in Flask: This article dives into URL routing in Flask, a critical aspect of web development, outlining its importance and mechanisms. It discusses defining routes, handling dynamic URLs, managing different HTTP methods, and dealing with redirects and errors. The content is tailored for developers with a basic grasp of Flask, guiding them through advanced concepts and best practices in URL routing.
  2. Exploring Flask’s URL Routing Features: The article presents a comprehensive overview of Flask’s URL routing capabilities, including creating basic and dynamic routes, using variable rules, and building URLs. It illustrates how Flask’s routing system enables developers to map URLs to specific functionalities, handle various request types, and produce appropriate responses based on user requests.
  3. Best Practices and Error Handling in Flask Routing: A significant portion of the article is dedicated to exploring best practices for effective URL routing in Flask. It emphasizes the importance of organized and readable URLs, the use of variables in URL patterns, clear error messaging, and the advantages of using Flask’s url_for function for URL building. Additionally, the article covers strategies for handling errors and redirects, ensuring a secure and user-friendly experience in Flask applications.

Flask and URL Routing

Flask is a popular web framework for Python that enables web developers to build web applications easily and efficiently. This is an advanced article on Flask, so you’ll need to have a basic understanding of how Flask works. You can get up to speed by looking at our introduction to Flask. You can also get up to speed by looking over the Flask documentation. One key features of Flask is its powerful URL routing system. URL routing is a fundamental concept in web development that involves mapping (binding) URLs to specific functionalities or resources within a web application. It’s a way of determining how incoming requests are handled, and by which view functions. Routing is about accepting requests and directing them to the appropriate view functions that will handle them and generate the desired response.

Basic Routing in Flask

Routing in Flask determines how incoming requests are handled based on the URL a user has requested. Flask uses the route() decorator method of the Flask application instance to define routes and then bind them to appropriate view functions. To demonstrate basic routing in Flask, we start by importing the Flask class from the flask module:
from flask import Flask
Once we have the Flask class, we can create the application instance and store it in a variable called app. The Flask class takes in a __name__ argument, which is a special Python variable denoting the name of the current module containing the Flask application instance:
app = Flask(__name__)
Using the application instance, we have access to its various methods and decorators, which we can use to define routes, handle requests, and perform other tasks in our web application. However, for this example, we’ll be interested in the route() decorator, a special method which, when applied to a function in Flask, turns it into a view function that will handle web requests. It takes in a mandatory URL pattern and optional HTTP methods as its arguments. The route() decorator enables us to associate a URL pattern with the decorated function, essentially saying that if a user visits the URL defined in the decorator, the function will be triggered to handle this request:
@app.route('/')
def index():
 return "This is a basic flask application"
In the code snippet above, we have the route(/) decorator applied to the index() function, meaning that the function will handle requests to the root URL ’/’. So when a user accesses the URL, Flask will trigger the index() function that will return the string “This is a basic Flask application”, and it will be displayed in the browser. To ensure the application runs when this module is invoked with Python in the command line, add the if __name__ check:
if __name__ == '__main__':
 app.run()
Putting all the above code snippets into one file gives us the following Flask application:
# app.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
 return "This is a basic flask application"

if __name__ == '__main__':
 app.run()
By using the route() decorator, we can define routes for different URLs and map them to the appropriate view functions that will generate the desired response. This allows us to create a structured and organized web application with distinct functionalities for different routes.

Variable Rules

In the example above, we created a simple URL. Flask enables us to create dynamic URLs that can respond to various scenarios, user input and specific requirements. By passing variables in URL patterns, developers can design routes that adapt dynamically and deliver personalized, engaging experiences to users. When defining routes in Flask, we can include variable placeholders marked by <variable_name> in the URL pattern. By default, these variables hold string values. However, if we need to pass other types of data, Flask provides converters that enable us to specify the type of data to be captured, like this: <converter:variable_name>. Below is an example diagram showing various variable URLs. The URLs change depending on the value a user supplies. For example, we could fetch a different product every time by giving a different ID, or we could show a different author profile by changing the username on the URL. An image showing URLs that take in variables Say we have a blogging application and we want to create a URL for a view that shows the profile of an author. We could pass the username of the author like so:
@app.route('/authors/<username>')
def show_author(username):
 return f"Return the author profile of {username}"
In this example, the URL pattern is '/authors/<username>', where <username> is the variable that will be replaced with the actual username of the author. It will be passed to the show_author() function as a parameter. Using this value, we can perform further actions, such as retrieving the author data from the database and generating a response based on the information we get from the database. We can also pass more than one variable in a URL:
@app.route('/posts/<int:post_id>/<slug>')
def show_post(post_id, slug):
 # carry out some processing like
 # retrieval from a database
 return f"Post {post_id} - Slug: {slug}"
In this example, we have a URL pattern that has more than one variable rule. It also incorporates a converter for the post_id in the form of <int:post_id>, indicating that an integer is expected to the variable. We also have <slug>, which will capture a slug string for this variable. So when a request is made to this URL, Flask will capture the values specified in the URL and pass them as arguments to the show_post() function for further processing. For example, if a request is made to /posts/456/flask-intro, Flask will capture post_id=456 and slug=flask-intro, and these values will be passed as arguments to the show_post() function. Within the function, we can perform various operations, such as retrieving the corresponding post from a database based on the post_id and slug values. In the example code, we simply return a string response that includes the captured values:
return f"Post {post_id} - Slug: {slug}"
This example shows how we can use variable rules and converters in Flask to create dynamic URLs that capture different types of data — such integers and strings — and process them within view functions. This allows us to build apps that respond to specific user input and deliver custom content.

URL Building

Once we define our URL patterns and map them to view functions, we can use them anywhere else in our code or in the templates, instead of hard coding the URLs Flask provides the url_for() function. The function will automatically build a URL depending on the arguments we provide to it. It takes the name view function as the first required argument and any number of optional keyword arguments, each corresponding to a variable part of the URL rule. Building URLs using the url_for() function has several benefits. It’s more descriptive in our code if we have something like url_for(‘login’) instead of /login. We’ll also be able to change our URLs in one go instead of needing to remember to manually change all hard-coded URLs. This function also handles escaping of special characters transparently and automatically. The generated URLs will be absolute paths, removing the problem of relative paths in browsers; no matter the structure of our application, the url_for() function will handle that for us properly. Let’s use the url_for() function to generate URLs for the view functions we’ve already seen above:
from flask import Flask, url_for

app = Flask(__name__)

@app.route('/')
def index():
 return "This is a basic flask application"

@app.route('/authors/<username>')
def show_author(username):
  return f"Return the author profile of {username}"

@app.route('/post/<int:post_id>/<slug>')
def show_post(post_id):
 return f"Showing post with ID: {post_id}"

if __name__ == '__main__':
 with app.test_request_context():
   # Generate URLs using url_for()
   home_url = url_for('index')
   profile_url = url_for('show_author', username='antony')
   post_url = url_for('show_post', post_id=456, slug='flask-intro' )

   print("Generated URLs:")
   print("Home URL:", home_url)
   print("Author profile URL:", profile_url)
   print("Post URL:", post_url)
This example demonstrates the usage of the url_for() function to generate URLs. In order to use the function, we import it from the flask module. It defines three routes: '/', '/authors/<username>', and '/post/<int:post_id>/<slug>'. Within the if __name__ == '__main__': block, a test request context is created using app.test_request_context() to allow access to the url_for() function. It tells Flask to behave as if it’s handling a request even while we use the shell. We then store the generated URLs in variables (home_url, profile_url, and post_url) and then print them, giving an output similar to the one shown below:
Generated URLs:
Home URL: /
Author profile URL: /authors/antony
Post URL: /post/456/flask-intro
We can also use the url_for() in templates. Let’s update the Flask application to render templates and see how we can move from one template to the other, by generating URLs using the url_for() function:
#app.py 
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
   return render_template("index.html")

@app.route('/authors/<username>')
def show_author(username):
   return render_template('profile.html', username=username)

if __name__ == '__main__':
 app.run()
Create a templates directory in the root of the project and create the following two files. index.html:
<!DOCTYPE html>
<html>
<head>
 <title>Home Page</title>
</head>
<body>
 <h1>Welcome to the home page!</h1>
 <a href="{{ url_for('show_author', username='Antony') }}">Visit Antony's profile</a>
</body>
</html>
profile.html:
<!DOCTYPE html>
<html>
<head>
 <title>User Profile</title>
</head>
<body>
 <h1>Welcome, {{ username }}!</h1>
 <a href="{{ url_for('index') }}">Go back to home page</a>
</body>
</html>
In the index.html template, we use the url_for() function to generate the URL for the 'profile' endpoint and pass the username argument as 'Antony'. This generates a link to Antony’s profile page. Similarly, in the profile.html template, we generate a link to the home page using url_for('index'). When the templates are rendered, Flask will replace {{ url_for(...) }} with the corresponding generated URLs. This allows for dynamic URL generation within the templates, making it easy to create links to other routes or pass arguments to those routes. Using url_for() in templates helps ensure that the generated URLs are correct and maintainable, even if the routes change in the future. It provides a convenient way to create dynamic links that adapt to the current state of our Flask application. Overall, we can see that, by using the url_for() function, we can dynamically generate URLs in Flask based on the route endpoints (the name of the view function) and other optional arguments. This provides a flexible and reliable way to create URLs that adapt to the specific functionalities of our web app.

HTTP Methods

Web applications use different HTTP methods when accessing URLs, and applications built using the Flask framework are no exception. Flask supports various HTTP methods such as GET, POST, PUT, DELETE and more. These methods define the actions we can carry out on the resources that are available when accessing the various URLs we’ve defined in our application. Using the different HTTP methods, we can handle different types of requests and perform related operations in our Flask application. In Flask, we can define the HTTP methods that a route can accept using the methods parameter of the route decorator. When we specify the methods a route accepts, Flask ensures that the route is only accessible for those specified methods. Here’s an example:
from flask import Flask, request

app = Flask(__name__)

@app.route('/', methods=['GET'])
def index():
 return "This is the home page"

@app.route('/authors', methods=['GET', 'POST'])
def authors():
 if request.method == 'GET':
    return "Get all authors"
 elif request.method == 'POST':
    # Create a new author
    return "Create a new author"

@app.route('/authors/<int:author_id>', methods=['GET', 'PUT', 'DELETE'])
def author(author_id):
 if request.method == 'GET':
    return f"Get author with ID: {author_id}"
 elif request.method == 'PUT':
    # Update author with ID: author_id
    return f"Update author with ID: {author_id}"
 elif request.method == 'DELETE':
    # Delete author with ID: author_id
    return f"Delete user with ID: {author_id}"

if __name__ == '__main__':
 app.run()
This updated code demonstrates the usage of HTTP methods in Flask. It defines three routes: '/','/authors', and '/authors/<int:author_id>'
. Each route has specific HTTP methods associated with it. The '/‘ route only allows GET requests, and the index() function handles GET requests to this route. It returns the string This is the home page when accessed via a GET request. We can omit the GET method parameter, since GET is the default for all methods unless explicitly stated. The '/authors' route allows both GET and POST requests, and the authors() function handles these requests. If the request method is GET, it returns the string Get all authors. If the request method is POST, it performs the necessary actions to create a new author and returns the string Create a new author. The '/authors/<int:author_id>' route allows GET, PUT, and DELETE requests, and the author() function handles these requests. If the request method is GET, it retrieves the author with the specified ID and returns a response string. If the request method is PUT, it updates the author with the specified ID and returns a response string. If the request method is DELETE, it deletes the author with the specified ID and returns a response string. By defining routes with specific HTTP methods, we can create a RESTful API or web application that handles different types of requests and performs the appropriate operations on the associated resources.

Redirects and Errors

As we go through the concept of routing in Flask, we also need to understand how to handle errors. Users will provide wrong URLs or incomplete information, and this will lead to errors occurring in our application. So for our application to be complete, we’ll need to handle errors gracefully — either by providing informative messages, or by redirecting users. Flask provides the redirect and abort functions. The redirect function is used to take the user to a new URL. It can be used in scenarios such as successful form submission, authentication, or when we want to guide a user to a different section of the application. It takes in the URL as an argument or the route name. It returns a status code 302 by default, but we can define our own custom status codes. To handle errors, the abort function is provided by Flask. It’s used to abort the processing of a request and return a HTTP error response. This will allow us to handle exceptional cases or errors in our application and respond with the appropriate HTTP status code and error page. Using this function, we can handle various errors in Flask, such as unauthorized access, invalid requests and other kinds of errors. We can choose the appropriate HTTP status code for the error, ensuring the client gets information about what went wrong. Here’s an example that shows how to use the two functions:
from flask import Flask, redirect, render_template, request, abort

app = Flask(__name__)

@app.route('/')
def home():
 return render_template('home.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
 if request.method == 'POST':
  # Perform login authentication
  username = request.form['username']
  password = request.form['password']

  # Check if the credentials are valid
  if username == 'admin' and password == 'password':
     # Redirect to the user's dashboard on successful login
           return redirect('/dashboard')
  else:
     # Abort the request with a 401 Unauthorized status code
     abort(401)

  return render_template('login.html')

@app.route('/dashboard')
def dashboard():
 return render_template('dashboard.html')

@app.errorhandler(401)
def unauthorized_error(error):
 return render_template('unauthorized.html'), 401

if __name__ == '__main__':
 app.run()
In this example, the /login route handles both GET and POST requests. When a POST request is received, it performs authentication with the provided credentials. If the credentials are valid, the user is redirected to the /dashboard route using the redirect function. However, if the authentication fails (such as when the user provides the wrong login information), the request is aborted with a 401 Unauthorized status code using the abort function. The user is then directed to an error page specified in the unauthorized_error error handler, which renders the unauthorized.html template and returns a 401 status code. By utilizing the redirect and abort functions together, we can effectively handle authentication failures and redirect users to appropriate pages or display relevant error messages, ensuring a secure and user-friendly login experience.

Best Practices for URL Routing in Flask

It’s important for our application to follow the best practices when creating URLs. Here are some of the most important to follow:
  • Organize URLs and make them easy to read. Group the related routes. This will make it easier to navigate and manage our codebase.
  • Make use of variables. Using variables in URL patterns will enable our application to handle dynamic requests from users. To do this, we can utilize rules such as <variable_name>. We can couple variables with converters in order to handle different kinds of data in our URLs.
  • Clear error messages. Ensure that, when handling errors in routes, we give clear and informative error messages to users. This will go a long way towards helping users understand why the errors happened and to taking the appropriate actions.
  • Utilize the url_for function. Building URLs using the url_for function ensures that our URLs are automatically generated and properly structured and consistent throughout the application, eliminating the need to hard code them.
By following these best practices, we can create well-organized and maintainable URL routing in our Flask applications. This leads to cleaner code, improved readability, better error handling, and more flexible and structured URLs.

Conclusion

In conclusion, understanding URL routing in Flask is essential for building user friendly and powerful web applications. By defining routes and mapping them to view functions, this allows developers to handle incoming requests and generate appropriate responses. When coupled with variables, we’re able to build more dynamic URL patterns, making the application more flexible and adaptable. Defining the kind of HTTP methods a route accepts enables an application to accept different types of request depending on the method defined for a route. Flask also provides features for handling errors and redirects. The redirect function enables us to redirect users to different URLs, while the abort function helps in handling errors and responding with appropriate HTTP status codes. Some of the best practices for URL routing in Flask include keeping routes organized and easy to read, using variables for dynamic URL patterns, providing clear messages for common errors, and properly structuring and generating URLs using the url_for function. By understanding URL routing concepts in Flask, and following these best practices, developers can create efficient, flexible and user-friendly web applications.

Frequently Asked Questions (FAQs) about Flask URL Routing

What is the significance of Flask URL routing in web development?

Flask URL routing plays a crucial role in web development. It is a mechanism that maps the specific URL with the associated function that is intended to perform a certain task. When a web application is developed using Flask, URL routing helps in directing the application’s user traffic to the correct webpage. It is the URL routing that determines what the user sees when they visit a particular URL. This is essential for creating a seamless and intuitive user experience, as it ensures that users can navigate the website or application easily and find the information or functionality they are looking for.

How can I use variables in Flask URL routing?

Variables can be used in Flask URL routing to create dynamic routes. This is done by placing the variable parts in the URL as sections marked by <variable_name>. When the route is requested, Flask will accept any text in that section of the URL and pass it as a keyword argument to your view function. For example, if you have a route like @app.route(‘/user/‘), you can access the username in your view function like this: def show_user_profile(username): return ‘User %s’ % username.

Can I use HTTP methods with Flask URL routing?

Yes, Flask URL routing supports the use of HTTP methods. By default, a route only answers to GET requests, but this can be changed by providing the methods argument to the route() decorator. For example, to handle POST requests, you can modify your route like this: @app.route(‘/login’, methods=[‘GET’, ‘POST’]). This means that the /login URL can be reached through both GET and POST requests.

How can I handle URL errors in Flask?

Flask provides a way to handle URL errors using error handlers. You can define an error handler for the 404 error (page not found) like this: @app.errorhandler(404) def page_not_found(error): return ‘This page does not exist’, 404. This function will be called whenever a 404 error occurs, and it will return the specified message and status code.

What is the use of url_for() function in Flask?

The url_for() function in Flask is used to generate URLs for a specific function. It accepts the name of the function as its first argument, and any number of keyword arguments, each corresponding to a variable part of the URL rule. For example, url_for(‘login’, next=’/’) would generate a URL like /login?next=/. This function is very useful for avoiding hardcoding URLs in your templates, which makes your application more flexible and easier to change.

How can I create a URL route with multiple parameters in Flask?

Creating a URL route with multiple parameters in Flask is straightforward. You just need to include multiple variable sections in your URL rule, each marked by <variable_name>. For example, if you have a route like @app.route(‘/post/int:post_id/‘), you can access the post_id and slug in your view function like this: def show_post(post_id, slug): return ‘Post %d, Slug: %s’ % (post_id, slug).

Can I use Flask URL routing to handle file uploads?

Yes, Flask URL routing can be used to handle file uploads. You would need to create a route that accepts POST requests, and use the request.files dictionary in Flask to access the uploaded file. You can then save the file to a location on your server using the save() method of the FileStorage object.

How can I create a URL route that matches any path in Flask?

Flask allows you to create a URL route that matches any path by using the special path:variable_name converter in your URL rule. For example, @app.route(‘/path/path:subpath‘) would match any path after /path/, and pass it as a string to your view function.

Can I use Flask URL routing to handle form submissions?

Yes, Flask URL routing can be used to handle form submissions. You would need to create a route that accepts POST requests, and use the request.form dictionary in Flask to access the form data. You can then process the form data as needed in your view function.

How can I redirect to another URL in Flask?

Flask provides the redirect() function to redirect to another URL. You just need to pass the URL to redirect to as the argument to this function. For example, return redirect(‘/login’) would redirect the user to the /login URL. You can also use the url_for() function to generate the URL to redirect to, based on a function name and arguments.

Kabaki AntonyKabaki Antony
View Author

Kabaki is a full-stack software engineer and a technical writer with a passion for creating innovative digital experiences. When not coding, he enjoys sharing knowledge with others by writing technical articles to help developers hone their skills.

flaskurl
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week