Hinweis: Installation in Thonny
- Menupunkt
Tools
>Manage Packages...
- Suche nach «Bottle»
- Install klicken
Was ist Bottle?
Bottle ist ein «Mikroframework» zum Erstellen einer Webseite oder einer Webapp. Bottle ist in Python geschrieben und bietet Routing, Templates und einen einfachen Webserver zum Testen an.
Erste Bottle-App
from bottle import abort, request, route, run, static_file, template
@route('/')
def index():
return 'Hello World!'
run(reloader=True, host='localhost', port=8080)
- Zeile 1
- wir importieren
route
undrun
ausBottle
(plus weitere Funktionen die wir später brauchen) - Zeile 3
- der
route
-Decorator bestimmt bei welcher URL die Funktion aufgerufen wird /
sagt, dass diese die Startseite ist- Zeile 4:
- wird die index-Funktion aufgerufen liefert diese Text zurück
- Zeile 7
- Wir starten den Webserver lokal auf Port 8080
- Dabei aktivieren wir den
reloader
, damit wir bei Änderungen nicht immer den Server neu starten müssen!
Wenn wir das Programm starten, so zeigt die Python-Shell folgende Ausgabe:
Bottle v0.12.25 server starting up (using WSGIRefServer())...
Listening on http://localhost:8080/
Hit Ctrl-C to quit.
Wir sehen also, dass der Server läuft und auf einen Kontakt wartet. Wir können nun im Browser die URL localhost
aufrufen – müssen allerdings noch den korrekten Port angeben:
Wir sollten den Text Hello World
im Browserfenster sehen. In der Python-Shell werden die requests
geloggt:
127.0.0.1 - - [30/Jan/2025 09:35:24] "GET / HTTP/1.1" 200 12
127.0.0.1 - - [30/Jan/2025 09:35:24] "GET /favicon.ico HTTP/1.1" 404 742
Der erste request /
ist der Aufruf von http://localhost/
– wir geben keinen Pfad an, nur die Hauptseite des Servers. Das Favicon wird beim Tab im Browser und, wie der Name vermuten lässt, in der Favoriten-Sammlung – also den Bookmarks verwendet. Der Browser ruft dieses automatisch auf: Unser Server sagt aber 404
, also nicht gefunden.
Routing
Im Beispiel haben wir eine Route für die Startseite eingebaut. Natürlich könnte unsere App auch Unterseiten haben, z.B. eine Seite mit Infos zur App und deren Erzeuger oder Detail-Seiten zu den Filmen/Serien.
Unterseiten
Unter http://localhost:8080/info soll eine allgemeine Informations-Seite angezeigt werden. Dazu hängen wir einfach folgenden Code ans Beispiel an:
@route("/info")
def info():
page = "Wir haben diese App im EF-Informatik erstellt!"
return page
dynamische Routen
Da man nicht für jeden Film/Serie eine eigene Route erstellen kann, gibt es dynamische Routen. In der Datenbank hat jeder Eintrag eine eindeutige Nummer, der Primärschlüssel, in unserem Beispiel das Feld id
. Wir können also auf einer Übersichtsseite Links zu Detail-Seiten generieren. Die Links sehen z.B. so aus: http://localhost:8080/film/597
597 ist dabei die id
des Films «Titanic». Wenn wir den Link aufrufen, sollten also Details zu «Titanic» erscheinen. Bottle muss also irgendwie zu dieser id
kommen und kann dann damit in der Datenbank die entsprechenden Informationen holen. Wir erstellen eine Route wie folgt:
@route("/film/<id:int>")
def film(id):
if id == 597:
return "Du möchtest mehr über den Film «Titanic» wissen."
abort(404)
Mit /film/<id>
legen wir eine Route fest, deren letzter Teil variabel ist. Mit <id:int>
sagen wir Bottle, dass wir den letzten Teil der URL als Argument id
vom Datentyp int
in der Funktion verwenden möchten.
mit Variablen aus dem Querystring
Wenn Werte aus einem Web-Formular abgeschickt werden, so sind diese im sogenannten Querystring zu finden. Dieser wir mit einem Fragezeichen an die URL angehängt.
In der Funktion search
decodieren wir den Query-String den wir im globalen request
-Objekt auslesen können. Wir erhalten so ein Dictionary und können die einzelnen Variablen (wir brauchen nur q
) daraus auslesen.
@route("/search")
def search():
query = request.query.decode()
return "Du willst nach " + query.q + " suchen?"
Statische Dateien liefern
Bilder, CSS-Dateien und andere «statische Dateien» (werden nicht dynamisch mit Inhalt aus der DB erzeugt) verstaut man am Besten in einem speziellen Unterordner, z.B. im Ordner static
. Dann kann man mit einer Route und einer Funktion sämtliche Dateien daraus liefern.
@route('/static/<filename>')
def static(filename):
return static_file(filename, root="./static")
- Zeile 27
- wir definieren die Route mit dem Platzhalter für die Datei
- Zeile 28
- wir definieren die Funktion welche die statische Datei zurückliefert
- Zeile 29
- wir verwenden die bottle-Funktion
static_file
, um die gewünschte Datei zurückzuliefern
Wenn sich im Unterordner static
eine Bilddatei namens logo.png
befindet, so kann man diese wie folgt aufrufen:
Statische Views (Templates) liefern
Templates schauen wir uns später noch genauer an – es handelt sich aber um HTML-Dateien mit eingebauten Platzhaltern. Wir können aber auch statische HTML-Dokumente (also ohne Platzhalter) verwenden. Dazu speichern wir die HTML-Datei im Ordner views
ab und übergeben ihren Namen der template
-Funktion:
@route("/about")
def about():
return template("about.html")
Verzeichnisstruktur
Eine Bottle-Webseite besteht aus dem Python-Skript im Projektordner. Die Vorlagen (Templates) werden zwingend im Unterverzeichnis views
abgespeichert. Statische Daten, also z.B. Bilder und CSS-Dateien, aber auch statische HTML-Dokumente, können wie oben beschrieben im Unterordner static
abgelegt werden.
projekt
├─ views
│ ├─ index.html
│ ├─ about.html
│ └─ search.html
├─ static
│ ├─ style.css
│ └─ logo.png
└─ main.py
Aufgabe: Webseite erstellen
Erstelle zu einem beliebigen Thema eine Webseite mit
- bottle als Webserver
- mehreren verlinkten Seiten (und den entsprechenden Routen)
- einigen Bildern
- einer css-Datei mit dem Design
Orientiere dich dabei am Skript – diese Seite und die nächsten Seiten über HTML und CSS sollten dir weiterhelfen.
- Offizielle Dokumentation
- https://bottlepy.org/docs/dev/index.html