Some Python Examples
← prev | next →     Top-level ToC     /web-dev.html     (printable version)

Bottle is one file (bottle.py). You can download it and drop it into your project dir, or else install it. I did apt-get install python3-bottle, which gives v0.12.7. Current unstable (which is pretty stable) is 0.13.

To create a bottle webapp, start with doing this:

mkdir my-webapp
cd my-webapp
wget http://bottlepy.org/bottle.py  # Directly gets the very latest bottle.
touch main.py
chmod +x main.py

Make main.py look like:

#!/usr/bin/env python3

import bottle

# Note `method` here is `GET` (the default if you omit `method`).
# You could also use `POST`.
@bottle.route('/hello/<name>', method='GET')  # "`<name>`" is a wildcard.
def index(name):
    return bottle.template('<b>Hello {{name}}</b>! Bottle version {{ver}}',
                           name=name, ver=bottle.__version__)

bottle.run(host='localhost', port=8080, debug=True)

Run that (./main.py), then point your browser to http://localhost:8080/hello/world.

Pages served will not have any doctype, html, or head tags. We’ll get back to how to include those.

When you run the webapp, you’re in bottle.run(…) until you Ctrl-C to stop the webapp. bottle.run waits for requests, services them, and waits for the next request.

Bottle handles requests sequentially; the previous request must complete and return a response before the next one is looked at.

Tutorial: http://bottlepy.org/docs/dev/tutorial.html.
See also: http://www.fullstackpython.com/bottle.html.

1 Bigger example

#!/usr/bin/env python3

import bottle

html_head = '''<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
'''

html_tail = '''</body>
</html>
'''

@bottle.route('/login')
def login():
    return html_head + '''<form action="/login" method="post">
Username: <input name="username" type="text" /> <br/>
Password: <input name="password" type="password" /> <br/>
<input value="Login" type="submit" />
</form>
''' + html_tail

@bottle.route('/login', method='POST')
def do_login():
    username = bottle.request.forms.get('username')
    password = bottle.request.forms.get('password')
    return html_head + 'U: ' + username + '<br/>\n' + \
                       'P: ' + password + '<br/><a href="/login">login</a>' + \
                       html_tail

bottle.run(host='localhost', port=8080, debug=True)

2 Notes about routing

@bottle.route('/<foo>')
def stuff(foo):
    return bottle.template('Hey {{someone}}!', someone=foo)

Terminology: /<foo> is the route, index is the callback.

Bottle passes the value for the wildcard (here, whatever <foo> is) as a keyword arg to the callback.

Routes may or may not end with a trailing slash. Bottle pays attention, and considers them different routes.

Instead of @route, you can use @get or @post (or @put, @delete, @patch). @get(...) == @route(...), and @post == @route('...', method='POST').

If you want, you can bind more than one route to a callback:

@bottle.route('/')
@bottle.route('/foo')
def root_or_foo():
    #...

You can use a “filtered” wildcard like so:

@bottle.route('/id-num/<id_num:int>')
def show_by_id(id_num):
    # `id_num` is an int.