Bottle¶
Bottle est un WSGI web-framework simple et rapide écrit en python qui est de plus packager en un seul fichier n’ayant aucune dépendance externe.
Core Features¶
Routes: Mapping URLs to code with a simple but powerful pattern syntax. Templates: Fast build-in template engine and support for mako, jinja2 and cheetah templates. Server: Build-in HTTP development server and support for paste, fapws3, flup, cherrypy or any other WSGI capable server. No dependencies: All in a single file and no dependencies other than the Python standard library.
Download / Install¶
Pour l’installer soit vous le télécharger et vous l’utiliser comme un simple fichier package soit vous l’installer via easy_install
easy_install -U bottle
Bottle peut être utilisé avec python 3 en utilisant 2to3
Features and Examples¶
Un exemple simple
from bottle import route, run
@route('/')
def index():
return 'Hello World!'
run(host='localhost', port=8080)
lancer le fichier python et aller voir sur http://localhost:8080/
Note
pour que le serveur puisse répondre quelque soit l’interfaces 127.0.0.1, 192.*.*.*, ... il faut utiliser comme host 0.0.0.0
Routes¶
@route() est un decorator qui permet de ciblé l’URL utilisé
@route('/hello/:name')
def hello(name):
return 'Hello, %s' % name
Templates¶
Bottle comporte aussi son propre système de template qui peut être appeler par le décorateur view
@route('/hello/template/:names')
@view('hello')
def template_hello(names):
names = names.split(',')
return dict(title='Hello World', names=names)
Dans ”./views/hello.tpl”:
<html>
<head>
<title>{{title}}</title>
</head>
<body>
%for name in names:
<p>Hello, <strong>{{name}}</strong></p>
%end
</body>
</html>
On peut aussi l’écrire ainsi
from bottle import template
@route('/hello/template/:names')
def template_hello(names):
names = names.split(',')
return template('view', dict(title='Hello World', names=names))
Warning
pour modifier le path des template on doit modifier la variable bottle.TEMPLATE_PATH; ex: TEMPLATE_PATH.insert(0,YOUR_PATH)
Bootle peut utiliser des template comme jinja2, mako ou cheetah
from bottle import mako_view as view
Static Files, Redirects and HTTP Errors¶
from bottle import static_file, redirect, abort
@route('/static/:filename')
def static_file(filename):
return static_file(filename, root='/path/to/static/files')
@route('/wrong/url')
def wrong():
redirect("/right/url")
@route('/restricted')
def restricted():
abort(401, "Sorry, access denied.")
@error(404)
def error404(error):
return template('error',{'error' :error,})
POST, GET, Header and Cookies¶
le plus facile est d’utiliser un dict()
from bottle import request, response, route
@route('/hello/cookie')
def cookie():
name = request.COOKIES.get('name', 'Stranger')
response.headers['Content-Type'] = 'text/plain'
return 'Hello, %s' % name
@route('/hello/cookie', method='POST')
def set_cookie():
if 'name' in request.POST:
name = request.POST['name']
response.set_cookie('name',name, path='/')
return 'OK'
Note
le path d’un cookie est important car il permet d’identifier les urls qui pourrons l’utiliser
Note
il est possible de crypter la valeur d’un cookie
et un exemple de login
from bottle import get, post, request
@get('/login') # or @route('/login')
def login_form():
return '''<form method="POST" action="/login">
<input name="name" type="text" />
<input name="password" type="password" />
<input type="submit" />
</form>'''
@post('/login') # or @route('/login', method='POST')
def login_submit():
name = request.forms.get('name')
password = request.forms.get('password')
if check_login(name, password):
return "<p>Your login was correct</p>"
else:
return "<p>Login failed</p>"
Session¶
Il n’y a pas de session avec Bottle mais on peut utiliser la notion de cookie
@app.route('/login')
def login():
username = request.forms.get('username')
password = request.forms.get('password')
if check_user_credentials(username, password):
response.set_cookie("account", username, secret='some-secret-key')
return "Welcome %s! You are now logged in." % username
else:
return "Login failed."
@app.route('/restricted')
def restricted_area():
username = request.get_cookie("account", secret='some-secret-key')
if username:
return "Hello %s. Welcome back." % username
else:
return "You are not logged in. Access denied."
HTTP Server¶
Bottle has a HTTP Server build in but also supports cherrypy, flup, paste and fapws3 as alternatives.
from bottle import PasteServer
run(server=PasteServer)
Gestion des Erreurs¶
le plus simple, contrairement a ce qu’on peut trouver sur la doc officiel, n’est pas de faire une route mais de modifier les handlers
voici un exemple simple
from bottle import Bottle, run, template, error, request
import os
TXT_ERROR_404 = """<h1>Error 404:</h1>
<br/><b>path:</b> %(path)s
<br/><b>url:</b> %(url)s
<br/><b>path scheme:</b> %(pathscheme)s
<br/><b>path netloc:</b> %(pathnetloc)s
<br/><b>path request:</b> %(pathrequest)s
<br/><b>path query :</b> %(pathquery)s
<br/><b>path fragment :</b> %(pathfragment)s
"""
app = Bottle()
def error404(error):
info = {
'path' : request.path,
'url' : request.url,
'pathscheme' : request.urlparts[0],
'pathnetloc' : request.urlparts[1],
'pathrequest' : request.urlparts[2],
'pathquery' : request.urlparts[3],
'pathfragment' : request.urlparts[4]
}
return TXT_ERROR_404 % info
def error500(error):
return 'error code 500'
handler = {
404: error404,
500: error500,
}
app.error_handler = handler
@app.route('/hello')
def hello():
return 1/0
run(app, host='0.0.0.0', port=8080)