Table of contents
1.
Introduction📄
2.
⭐Request Routing
3.
⭐Rule Syntax
4.
⭐Dynamic Routes
5.
Filters
5.1.
Examples📄
6.
HTTP Requests Methods
7.
Special HTTP Methods🔥
7.1.
Head
7.2.
Any
8.
Routing Static Files🌐
9.
Error Messages🌐
10.
Explicit Routing Configuration🌐
11.
Frequently Asked Questions
11.1.
What are Django and Bottle?
11.2.
What is the Bottle web framework?
11.3.
Can bottles be used in complex applications?
11.4.
How do I stop a server of bottles?
11.5.
What is a bottle library?
12.
Conclusion
Last Updated: Mar 27, 2024
Easy

Request Routing in Bottle Web Framework

Author Mayank Goyal
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction📄

For each request, Bottle's robust routing engine determines the appropriate callback. The course explains the fundamentals. This article goes to great length on advanced approaches and rule mechanics.

Bottle Framework

So, without any further ado, let's get started!

Request Routing

The route() decorator adds a new route to the default application and ties a URL path to a callback function. A single route application, though, can get a little monotonous. Let's add a few more, keeping in mind the bottle import template:

@route('/')
@route('/hello/<name>')
def greet(name='Stranger'):
    return template('Hello {{name}}, how are you?', name=name)

This example shows two things: you can add wildcards to URLs, access them via keyword arguments, and bind many routes to a single callback.

Bottle framework image

Rule Syntax

The Router makes a distinction between static routes (such as /contact) and dynamic routes (such as /hello/<name>). A route is deemed dynamic if it contains one or more wildcards. The rest are static routes.

The most basic wildcard type is an enclosed name in angle brackets, such as <name>. The name must be distinct for a certain route and constitute an acceptable Python identifier (alphanumeric, starting with a letter). This is due to the later request callback using wildcards as keyword parameters.

Each wildcard only matches the first slash (/) and one or more characters, but not more. This ensures that just one path segment is matched and routes with multiple wildcards remain unambiguous and equal a regular expression of [^/]+.

Dynamic Routes

Unlike static routes, which can match one URL at a time, dynamic routes can match many URLs simultaneously. A straightforward wildcard is a name contained in angle brackets (for example, <name>), which takes any number of characters up to the subsequent slash (/).For example, the route /hello/<name> accepts requests for /hello/mayank as well as /hello/Soham, but not for /hello, /hello/ or /hello/Mr/debojeet.

Dynamic Routes

Each wildcard sends the request callback's keyword argument and the portion of the URL it has covered. You may put them to use right now and easily construct RESTful, attractive, and meaningful URLs. Here are some additional instances and the URLs they would match:

@route('/wiki/<pagename>') # matches /wiki/Learning_Python
def show_wiki_page(pagename):
    ...


@route('/<action>/<user>') # matches /follow/defnull
def user_api(action, user):

Filters

Before the matched portion of the URL is delivered to the callback, filters are used to create more precise wildcards and modify the matched portion of the URL. The declaration of a filtered wildcard is <name:filter> or <name:filter:config>. The optional config part's syntax will vary depending on the filter used.

The following filters are used by default, although more could be added:

Filters                                         Description
int only (signed) digits are matched, and the value is transformed into an integer.
float Similar to int, but for decimal numbers.
path matches all characters, including the slash character, in a non-greedy manner and can be used to match more than one path segment. 
:re The value that matches remains unchanged.

Examples📄

Let's look at some real-world instances:

@route('/object/<id:int>')
def callback(id):
    assert isinstance(id, int)


@route('/show/<name:re:[a-z]+>')
def callback(name):
    assert name.isalpha()


@route('/static/<path:path>')
def callback(path):
    return static_file(path, ...)

 

The Router allows you to install your filters. All you require is a function that yields three items:

A regular expression string.

A callable that translates the URL fragment into a python value.

A callable that performs the opposite.

The configuration string is the only parameter passed to the filter function, which has the option of parsing it as necessary:

app = Bottle()


def list_filter(config):
    ''' Matches a comma-separated list of numbers. '''
    delimiter = config or ','
    regexp = r'\d+(%s\d)*' % re.escape(delimiter)


    def to_python(match):
        return map(int, match.split(delimiter))


    def to_url(numbers):
        return delimiter.join(map(str, numbers))


    return regexp, to_python, to_url


app.router.add_filter('list', list_filter)


@app.route('/follow/<ids:list>')
def follow_users(ids):
    for id in ids:

HTTP Requests Methods

The HTTP protocol specifies the number of request methods (sometimes known as "verbs") for various activities. GET is the default for all routes if no additional method is provided. Only GET these routes will match requests. Add a method keyword argument to the route() decorator or use one of the five alternative decorators to support different methods, such as POST(post()), PUT(put()), DELETE(delete()), PATCH(patch()) , or get().

HTML form submission often makes use of the POST method. Here's an illustration of how to use POST to handle a login form:

Special HTTP Methods🔥

Head

The GET method seeks a response identical to a HEAD request but without the response body. This benefit is getting meta-data about a resource without downloading the whole thing. Bottle automatically responds to these requests by switching to the correct GET route and, if necessary, removing the requested content. You do not need to provide any HEAD routes manually.

Any

Routes that listen to ANY will match requests regardless of their HTTP method, but only if no other more particular route is established. The non-standard ANY method functions as a low-priority fallback. This is advantageous for proxy routes that route traffic to more specialized sub-applications.

In conclusion, HEAD requests fall back to GET routes, and all requests fall back to ANY routes only if the initial request method does not match a route. That's all there is to it.

Routing Static Files🌐

Images and CSS files are static files that are not automatically served. To manage which files are provided and where they are located, you must create a route and a callback:

from bottle import static_file
@route('/static/<filename>')
def server_static(filename):
    return static_file(filename, root='/path/to/your/static/files)


The static file() function is a tool for serving files conveniently and securely. Because the filename> wildcard won't match a path with a slash, this example is restricted to files located precisely within the /path/to/your/static/files directory. The wildcard should be changed to the path filter to serve files in subdirectories:

@route('/static/<filepath:path>')
def server_static(filepath):
    return static_file(filepath, root='/path/to/your/static/files)


Using a relative root-path like root='./static/files' requires caution. The project directory is not the same as the working directory (./).

Error Messages🌐

The bottle shows a helpful yet uncomplicated error page if something goes wrong. The error() decorator allows you to override the default for a particular HTTP status code:

from bottle import error
@error(404)
def error404(error):
    return 'Sorry, Double Trouble!!!'


404 File Not Found errors will present the user with a unique error page. An instance of HTTPError is the only parameter supplied to the error-handler. An ordinary request callback and an error-handler are very similar, other than that. Except for HTTPError instances, you can read from the request, write to the response, and return any supported data type.

Only in cases where your application returns or raises an HTTPError exception (abort() does just that) should you employ error handlers. The error handler won't be activated by updating the Request. Status or returning HTTPResponse.

Explicit Routing Configuration🌐

The route decorator method can also be called directly. This approach offers flexibility in intricate settings by giving you direct control over the when and how of routing configuration.

The following is a simple example of explicit routing configuration using the default bottle application:

def setup_routing():
    bottle.route('/', 'GET', index)
    bottle.route('/edit', ['GET', 'POST'], edit)


In reality, the same configuration can be used for any Bottle instance routing:

def setup_routing(app):
    app.route('/new', ['GET', 'POST'], form_new)
    app.route('/edit', ['GET', 'POST'], form_edit)


app = Bottle()
setup_routing(app)

Frequently Asked Questions

What are Django and Bottle?

Model-template-view (MTV) is the basis for its design. It adheres to the "batteries included" tenet and a wide range of tools that application developers require, including an ORM framework, admin panel, directory structure, and more. The Bottle is a Python WSGI micro web framework that is quick, easy, and lightweight.

What is the Bottle web framework?

The Bottle is a Python WSGI micro web framework that is quick, easy, and lightweight. It is supplied as a single file module and only requires the Python Standard Library as a dependency. Routing: Support for clean and dynamic URLs and requests to function-call mapping.

Can bottles be used in complex applications?

The Bottle is a micro-framework for prototyping and creating quick online services and apps. It helps you complete tasks quickly and out of the way. Still, it lacks several sophisticated capabilities and ready-to-use solutions in other frameworks (MVC, ORM, form validation, scaffolding, XML-RPC). The Bottle allows you to add these capabilities and create complicated apps, but you should consider adopting a full-stack Web framework, such as pylons or paste.

How do I stop a server of bottles?

There is no issue with launching a bottle webserver without a thread or subprocess. CTRL + c to quit the bottle app.

What is a bottle library?

The Bottle is a Python WSGI micro web framework that is quick, easy, and lightweight. It is supplied as a single file module and only requires the Python Standard Library as a dependency.

Conclusion

This article taught us how to request routing, the rules associated with requesting, different filter methods, and some special HTTP methods. That’s all from the article. I hope you all like it.

Always be curious to learn code!

To learn more about different frameworks, you can refer to the 19 best python frameworks and flask introduction

That's the end of the article. I hope you all like this article. 

Do upvote our blogs if you find them helpful and engaging!

Happy Learning, Ninjas!

Thankyou image
Live masterclass