Bottle, Formulare, Routen und POST

Django, Flask, Bottle, WSGI, CGI…
Antworten
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hallo zusammen,

meine Frage lautet kurz und knapp: Was ist ein guter Weg, um mit bottle Formulare auszuliefern und die Ergebnisse zu verarbeiten?

Ich dachte als erste Eingebung daran, eine einzelne Route du definieren, die sich sowohl um die Auslieferung des Formulars als auch um die Auswertung kümmert, wie im unteren Beispiel angedeutet zu sehen ist:

Code: Alles auswählen

@route("/ask", method="POST")
def ask_question():
    if request.POST.get("ask", "").strip():
        # Daten verarbeiten
        # zurück zum Index oder sonst wohin
        redirect("/")
    else:
        # Formular ausliefern
        return "formular"

Code: Alles auswählen

<form action="/ask" method="POST">
<!-- irgend welche Elemente -->
<input type="submit" value="ask"/>
</form>
Hierbei bekomme ich (natürlich) einen 404 Fehler, wenn ich das ganze z.B. von einer Hauptseite aus anspreche, da über einen Link ja nicht POST genutzt wird. Oder kann man das irgend wie "simulieren"?

Eine Möglichkeit wäre es natürlich wie im Tutorial von bottle einfach GET zu nutzen; aber das ist ja eher ein workaround.

Ich sehe ich eigentlich nur die Möglichkeit, zwei Routen zu definieren, eine fürs Ausliefern des Formulars und eine fürs Auswerten. Problem dabei: Schlägt die Formularvalidierung fehl, so will ich die bisherigen Daten ja gerne wieder ans Template übergeben...

Nuja, vielleicht habe ich ja auch ein Brett vorm Kopf und die Erleuchtung ist trivial möglich :-)
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Du kannst doch beide Routen für die gleiche Funktion definieren.

Code: Alles auswählen

@route("/ask", method="POST")
@route("/ask", method="GET")
def ask_question():
    if request.method == 'POST':
        if handle_formdata(request.POST):
            redirect("/")
    return "<form>"
Oder etwas übersichtlicher:

Code: Alles auswählen

@route("/ask", method="POST")
def form_post():
    # ...handle request.POST data...
    if all_ok:
        redirect("/")
    return form_get()

@route("/ask", method="GET")
@view('<form>')
def form_get():
    # request.POST may contain data, because this function
    # is also called from a POST callback.
    return dict(...)
Eine Route verändert eine Funktion in keiner Weise. Man kann sie also weiterhin als Funktion benutzen und von anderen Route-Callbacks aus aufrufen. Solche "internen Redirects" sind deutlich effizienter als externe.
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Defnull hat geschrieben:Du kannst doch beide Routen für die gleiche Funktion definieren.
*Patsch* :oops:
Oh mann, bin wirklich nicht ausgeschlafen. Ich bin mir im Moment noch nicht sicher, ob ich die zweite Version übersichtlicher finde; das muss ich mir mal in meinem Code angucken.

Aber danke für die prompte Antwort :-)
Antworten