% Web Development Have a look at [Django](https://www.djangoproject.com/) or [Flask](http://flask.pocoo.org/). That said, for a *really* fast way to get started, [Bottle](http://bottlepy.org/docs/dev/index.html) is one file (bottle.py). You can download it and drop it into your project dir, or else install it via apt. Bottle ====== To create a bottle webapp, start with: ~~~ 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: ~~~python #!/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/', method='GET') # "``" is a wildcard. def index(name): return bottle.template('Hello {{name}}! 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 . 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: . | See also: . Bigger example -------------- ~~~python #!/usr/bin/env python3 import bottle html_head = ''' ''' html_tail = ''' ''' @bottle.route('/login') def login(): return html_head + '''
''' + 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 + '
\n' + \ 'P: ' + password + '
login' + \ html_tail bottle.run(host='localhost', port=8080, debug=True) ~~~ Notes about routing ------------------- ~~~python @bottle.route('/') def stuff(foo): return bottle.template('Hey {{someone}}!', someone=foo) ~~~ Terminology: `/` is the route, `index` is the callback. Bottle passes the value for the wildcard (here, whatever `` 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: ~~~python @bottle.route('/') @bottle.route('/foo') def root_or_foo(): #... ~~~ You can use a "filtered" wildcard like so: ~~~ @bottle.route('/id-num/') def show_by_id(id_num): # `id_num` is an int. ~~~