Understanding Routes

source: bottlepy.org

Now it is time to introduce Bottle in order to create a web-based application. But first, we need to look into a basic concept of Bottle: routes.

Basically, each page visible in the browser is dynamically generated when the page address is called. Thus, there is no static content. That is exactly what is called a “route” within Bottle: a certain address on the server. So, for example, when the page http://localhost:8080/todo is called from the browser, Bottle “grabs” the call and checks if there is any (Python) function defined for the route “todo”. If so, Bottle will execute the corresponding Python code and return its result.

So, after understanding the concept of routes, let’s create the first one. The goal is to see all open items from the ToDo list:

import sqlite3
from bottle import route, run

@route('/todo')
def todo_list():
    conn = sqlite3.connect('todo.db')
    c = conn.cursor()
    c.execute("SELECT id, task FROM todo WHERE status LIKE '1'")
    result = c.fetchall()
    return str(result)

run()

Save the code a todo.py, preferably in the same directory as the file todo.db. Otherwise, you need to add the path to todo.db in the sqlite3.connect() statement.

Let’s have a look what we just did: We imported the necessary module sqlite3 to access to SQLite database and from Bottle we imported route and run. The run() statement simply starts the web server included in Bottle. By default, the web server serves the pages on localhost and port 8080. Furthermore, we imported route, which is the function responsible for Bottle’s routing. As you can see, we defined one function, todo_list(), with a few lines of code reading from the database. The important point is the decorator statement @route('/todo') right before the def todo_list() statement. By doing this, we bind this function to the route /todo, so every time the browsers calls http://localhost:8080/todo, Bottle returns the result of the function todo_list(). That is how routing within bottle works.

Actually you can bind more than one route to a function. So the following code:

@route('/todo')
@route('/my_todo_list')
def todo_list():
    ...

will work fine, too. What will not work is to bind one route to more than one function.

What you will see in the browser is what is returned, thus the value given by the return statement. In this example, we need to convert result in to a string by str(), as Bottle expects a string or a list of strings from the return statement. But here, the result of the database query is a list of tuples, which is the standard defined by the Python DB API.

Now, after understanding the little script above, it is time to execute it and watch the result yourself. Remember that on Linux- / Unix-based systems the file todo.py needs to be executable first. Then, just run python todo.py and call the page http://localhost:8080/todo in your browser. In case you made no mistake writing the script, the output should look like this:

[(2, u'Visit the Python website'), (3, u'Test various editors for and check the syntax highlighting')]

If so - congratulations! You are now a successful user of Bottle. In case it did not work and you need to make some changes to the script, remember to stop Bottle serving the page, otherwise the revised version will not be loaded.

Actually, the output is not really exciting nor nice to read. It is the raw result returned from the SQL query.

So, in the next step we format the output in a nicer way. But before we do that, we make our life easier.