5. Routing

When a request is made to a Lona app, the routing table is used to determine which view should be run. The routing table is a list of lona.Route objects, that gets iterated over until the first route matches (therefore the order may be important in some cases).

All examples in this tutorial use the app.route decorator, which appends a new route, with the decorated view in it, to the routing table. Therefore the views and routes in a Lona script get tried top to bottom when a request comes in.

Routes use regexes with named parameters, that are generated at setup time. By default, URL args match every character between two slashes, because most URL schemas use slashes as dividers. /user/<username>/<nickname> will match URLs like /user/alice/@alice_1. To define a custom pattern add a colon to a URL arg like this: /user/<username:[a-z]{3}>/<nickname>.

To create a route that matches any given route, lona.MATCH_ALL can be used instead of a URL.

This example shows a simple greeting view, that uses an URL arg as name.

from lona_picocss.html import InlineButton, TextInput, HTML, H1, P
from lona_picocss import install_picocss

from lona import RedirectResponse, View, App

app = App(__file__)

install_picocss(app, debug=True)


# setup the route
@app.route('/hello/<name>')
class GreetView(View):
    def handle_request(self, request):

        # all url args and the route are available in the
        # request object
        name = request.match_info['name']

        return HTML(
            H1(f'Hello {name}'),
            P('How are you?'),
        )


# index view
@app.route('/')
class Index(View):
    def handle_button_click(self, input_event):

        # redirect to the view with the special route
        return RedirectResponse(
            f'/hello/{self.text_input.value}'
        )

    def handle_request(self, request):
        self.text_input = TextInput(
            placeholder='Name',
        )

        return HTML(
            H1('Enter Your Name'),
            self.text_input,
            InlineButton('Greet Me', handle_click=self.handle_button_click),
        )


if __name__ == '__main__':
    app.run()

Reverse Matching

In the previous example, the index view used the URL as string to redirect to the greeting view. That means that both the index view, and the greeting view have to be changed when the URL changes.

When a route has a name, which can be any string, a complete URL can be reverse matched using Server.reverse()

from lona_picocss.html import InlineButton, TextInput, HTML, H1, P
from lona_picocss import install_picocss

from lona import RedirectResponse, View, App

app = App(__file__)

install_picocss(app, debug=True)


# give this route the name 'greet-view'
@app.route('/hello/<name>', name='greet-view')
class GreetView(View):
    def handle_request(self, request):
        name = request.match_info['name']

        return HTML(
            H1(f'Hello {name}'),
            P('How are you?'),
        )


@app.route('/')
class Index(View):
    def handle_button_click(self, input_event):
        return RedirectResponse(

            # use route name instead of the hard coded value
            self.server.reverse('greet-view', name=self.text_input.value),
        )

    def handle_request(self, request):
        self.text_input = TextInput(
            placeholder='Name',
        )

        return HTML(
            H1('Enter Your Name'),
            self.text_input,
            InlineButton('Greet Me', handle_click=self.handle_button_click),
        )


if __name__ == '__main__':
    app.run()
More information: