Button, soll Python Funktion aufrufen

Django, Flask, Bottle, WSGI, CGI…
Antworten
Susanne
User
Beiträge: 35
Registriert: Dienstag 8. Januar 2013, 19:49

Hallo,

ich bin gerade dabei eine Homepage zu programmieren, dabei will ich mit den Basic beginnen.
ich habe mir eine html Seite gemacht bei der ich auch schon daten von meiner view anzeigen lassen kann. Nun aber will ich einen Button in meine html Seite einbinden. Ich würde gerne eine View programmieren, die ein print Befehl in meiner Konsole ausgibt

mein html Code sieht wie folgt aus:

Code: Alles auswählen

<input class="button" 
type="button" type="submit" value="Test" name= "Test" 
onclick=""
></input> 
meine View sieht wie folgt aus:

Code: Alles auswählen

def wohnzimmer(request):

    if "Test" in request.GET:    
        print 'Sie haben einen Button gedrückt'
        Button = 'Dieser Kommentar wird in meiner HTML-Seite angezeigt!!!'
    return render(request,'test.html', {'Button': Button,})
wie muss meine onclick Methode in html aussehen, dass ich diese Funktion aufrufen kann?
BlackJack

@Susanne: Dazu baut man ein <form> in die Webseite ein, zu dem das <input> gehören muss, und die Aktion vom Form muss eine URL sein, die auf die `wohnzimmer()`-Funktion abgebildet wird. `onclick` braucht man dafür gar nicht. Das ist dazu da JavaScript im Browser auszuführen.

Das ``print`` landet übrigens nicht in der Konsole sondern üblicherweise im Log vom Webserver. Zumindest wenn das so im Webrahmenwerk und im Webserver so konfiguriert ist.
Susanne
User
Beiträge: 35
Registriert: Dienstag 8. Januar 2013, 19:49

aahhh... jetzt kommt folgende Meldung:

Forbidden (403)

CSRF verification failed. Request aborted.
Help

Reason given for failure:

CSRF token missing or incorrect.


In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:

Your browser is accepting cookies.
The view function uses RequestContext for the template, instead of Context.
In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.

You're seeing the help section of this page because you have DEBUG = True in your Django settings file. Change that to False, and only the initial error message will be displayed.

You can customize this page using the CSRF_FAILURE_VIEW setting.


was hat das zu bedeuten?


mein Button sieht wie folgt aus:

Code: Alles auswählen

 <form method="post" action="?Wohnzimmer"> 
      <input type="submit" value="Abschicken" /> 
    </form>
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Das bedeutet genau das was dransteht.
Für Leute, die keine Lust zum Lesen haben:
Es fehlt ein

Code: Alles auswählen

{% csrf_token %}
innerhalb des <form>-Elements
BlackJack

@Susanne: Die Django-Dokumentation zu CSRF hast Du gelesen? So ganz grob sagt die Meldung ja auch schon was man machen muss, damit POST sicher funktioniert.

Ist POST überhaupt die richtige Wahl? Das impliziert, dass der Aufruf der URL einen Zustand innerhalb der Anwendung ändert. Also zum Beispiel den Datenbankinhalt.

Das Fragezeichen in der `action` ist ein bischen ungewöhnlich. Wenn man fixe Werte im „query string” haben möchte, dann benutzt man dafür in der Regel versteckte Felder im <form>.
Susanne
User
Beiträge: 35
Registriert: Dienstag 8. Januar 2013, 19:49

Im mom sieht so meine Funktion aus:

Code: Alles auswählen

def wohnzimmer(request):

    if "Wohnzimmer" in request.GET: 
        name = request.POST.get("Wohnzimmer") 
        print name
        "Zeig an wo Sie den Button gedrückt haben"
        Button = 'Sie haben den Schalter im Wohnzimmer gedrückt'
        return render(request,'articles.html', {'Button': Button,})
und so habe ich meine html Seite geschrieben. Allerdings hab ich das Gefühl, dass nichts ausgelöst wird. Kann aber den Fehler auch nicht finden

Code: Alles auswählen

 <form  method="post" action="?Wohnzimmer"> {% csrf_token %}
      <input type="submit" value="Wohnzimmer" /> 
    </form>
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Susanne: jeder Webserver loggt normalerweise mit, welche Seiten aufgerufen werden.
Da kannst Du also nachschauen, ob und wenn ja welche URL aufgerufen wird.

Im Moment schickt Deine <form> als Parameter einen leeren GET-Parameter »Wohnzimmer«,
wegen des action="?Wohnzimmer" und einen »csrfmiddlewaretoken« als POST-Parameter,
wegen des {% csrftoken %}.
Das <input>-Feld wird nicht mitgeschickt, weil es keinen Namen hat.

Es ist sehr ungewöhnlich, gleichzeitig sowohl POST- als auch GET-Parameter zu verwenden.
(siehe Blackjack)
Susanne
User
Beiträge: 35
Registriert: Dienstag 8. Januar 2013, 19:49

Ok, bin ich soweit von meiner Lösung entfernt?
könnte mir vielleicht jemand sagen wie es richtig geht?

vielen Dank im voraus?
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Trotz allem Unüblichen ist an den Fragmenten die Du gepostet hast nur der
fehlende Name im <input> »falsch«, was aber nur Auswirkungen auf

Code: Alles auswählen

name = request.POST.get("Wohnzimmer")
hat.
Susanne
User
Beiträge: 35
Registriert: Dienstag 8. Januar 2013, 19:49

Nun habe ich ein Input attribut gesetzt und folgender html tag geschrieben.

<input class="navibutton"
type="submit" value="Wohnzimmer"
onclick="navi.action='{% url Project.views.wohnzimmer %}'"
> {% csrf_token %}
</input>

Nun kommt folgende Fehlermeldung:
Reverse for 'Project.views.wohnzimmer' with arguments '()' and keyword arguments '{}' not found.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Sind wir hier beim Topfschlagen? Kalt, kälter, gaanzgaanz kalt.

Programmieren ist nicht »Lustig rumraten bis es zufällig funktioniert«.
Zumindest die Grundlagen der Fehlersuche sollte man schon beherrschen.

Die Fehlermeldung sagt, dass es keinen pattern-Eintrag in urls.py gibt,
der die Methode Project.views.wohnzimmer aufruft.

Diese seltsame onclick-Methode wird Dein Problem immer noch nicht lösen
und das <input>-Element hat immer noch keinen Namen.

Hast Du Dir überhaupt schon die Web-Server-Logs angeschaut?
Susanne
User
Beiträge: 35
Registriert: Dienstag 8. Januar 2013, 19:49

Ich nehm Django.
gibt es da überhaupt Logfiles?
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Beim django-integrierten Webserver ist das die Konsole,
für andere Web-Server entsprechend der Konfiguration die normalen Access-, bzw. Error-Logs.
BlackJack

@Susanne: Wenn Du Django auch als Webserver verwendest, dann ist das der eingebaute Webserver der hauptsächlich zum entwickeln gedacht ist, und der hat selbstverständlich Logausgaben. Sonst könnte man damit schlecht entwickeln wenn man nicht nachvollziehen könnte was der tut. Das ist ja zur Fehlersuche, und die ist Bestandteil vom Entwickeln, essentiell.

Das `csrs_token`-Tag ist an einer merkwürdigen Stelle im Template eingefügt. Das kann man wohl zur Liste der Merkwürdigkeiten hinzufügen.
Susanne
User
Beiträge: 35
Registriert: Dienstag 8. Januar 2013, 19:49

Ok, jetzt habe schon sooft gehört dass es falsch ist wie ich es mache. Kann mir jemand sagen wie man es richtig macht? Es ist bestimmt ne kleinigkeit will nur, dass wenn ich au einen Button drücke eine funktion ausgeführt wird
BlackJack

@Susanne: Diese scheinbar einfache Frage ist IMHO nicht so einfach zu beantworten. Es gäbe da mehrere Möglichkeiten, je nach Rahmenbedingungen. Und als Kleinigkeit würde ich das nicht bezeichnen. Da steht immerhin ein Browser, HTML, möglicherweise JavaScript, HTTP, und ein Webrahmenwerk zwischen dem Klick und dem Funktionsaufruf.

Die erste Frage die sich stellt ist was möchtest Du *eigentlich* machen. Was ist das Ziel dieser Aktion — konkret und nicht so abstrakt mit Schaltfläche und Funktion. Ist das wirklich alles oder kommt da, möglicherweise später, noch mehr hinzu. Denn nur Schaltfläche und Funktion, dafür wäre mir persönlich Django zu überdimensioniert.

Grundvoraussetzung sind in jedem Fall neben Python noch HTML-Kenntnisse. Und ein wenig HTTP, also zumindest das man versteht was Browser und Webserver so an Daten austauschen bei GET- und POST-Anfragen und wo die in <form>s und im Webrahmenwerk wieder auftauchen.

Wenn Du Django verwenden möchtest, dann solltest Du das Tutorial in der Dokumentation mal durcharbeiten.

Grundsätzlich musst Du den Aufruf Deiner Funktion mit einer Anfrage vom Browser verbinden. Das einfachste wäre hier die Seite mit dem Button wieder auszuliefern. Dann brauchst Du entweder zwei fast indentische Seiten: Eine Einstiegsseite mit dem Button und einem Link zur zweiten URL welche die Funktion ausführt und die Seite mit dem Button und einem Link auf sich selbst ausliefert. Oder Du löst das mit einer Seite und einem Wert in der Anfrage der angibt, dass nicht nur der Button angezeigt werden soll, sondern auch die Funktion ausgeführt werden soll. Man kann hier mit <form> und <input> arbeiten. Im zweiten Fall dann neben dem <input> für die Schaltfläche noch mit einem „versteckten” <input>, das einen Aufruf der Funktion auslösen soll.

Statt mit <form> und <input> zu arbeiten könnte man hier übrigens auch einfache Links verwenden und die gegebenenfalls mit CSS als Schaltfläche gestalten. Wenn man schon CSS wie zum Beispiel Twitter's Bootstrap eingebunden hat, bietet sich so etwas an.

Falls die Anforderung ist, dass man die Funktion über die Schaltfläche auslösen kann, ohne dass die Webseite neu geladen wird, dann braucht man zwingend zwei URLs, also eine eigene für die Ausführung der Funktion. Und man braucht JavaScript und damit Kenntnisse in einer weiteren Programmiersprache und entweder Browsern direkt oder einer Bibliothek die Ajax-Anfragen über verschiedene Browser vereinheitlicht und vereinfacht. `jQuery` ist da eine beliebte Bibliothek die unter anderem etwas für Ajax bietet.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Um beim ursprünglichen Beispiel zu bleiben:

views.py:

Code: Alles auswählen

def wohnzimmer(request):
    if "schalter" in request.POST:
        name = request.POST.get("schalter")
        print name
        if name == "Wohnzimmer":
            Button = 'Sie haben den Schalter im Wohnzimmer gedrückt'
            return render(request,'articles.html', {'Button': Button,})
    return HttpResponseForbidden()

def index(request):
    return render(request,'index.html')
index.html:

Code: Alles auswählen

<html>
<body>
    <form method="post" action="{% url view_wohnzimmer %}"> {% csrf_token %}
      <input type="submit" name="schalter" value="Wohnzimmer" />
    </form>
</body>
</html>
und natürlich eine urls.py

Code: Alles auswählen

from django.conf.urls import patterns, url
urlpatterns = patterns('myproject.views',
    url(r'^', 'index'),
    url(r'^wohnzimmer.html', 'wohnzimmer', name="view_wohnzimmer"),
)
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@Susanne: Wie BlackJack gerade fast zeitgleich schrieb ist Webentwicklung eine durchaus komplexe Angelegenheit, bei der man in mehreren Disziplinen sattelfest sein muss.

Was Django betrifft, geht es im Prinzip so:
Du hast eine urls.py Datei in der die url-Patterns den View-Funktionen zugeordnet werden. Dort gibt es übrigens auch ein sehr praktisches name-Attribut.

In Templates kannst Du mit dem url-Template-Tag von Django die in der urls.py Datei definierten urls erzeugen lassen; dafür muss die entsprechende View aber auch in urls.py aufgeführt sein. Deine Fehlermeldung sagt aus, dass an dieser Stelle ein Problem auftritt.

Im Falle eines Formulars verwendest Du im form-Tag das url-Template-Tag als Parameter des action-Attributes. Dann wird durch Klick eines Buttons vom Type "Submit" die gewünschte Funktion aufgerufen.

Geh einfach mal in Ruhe das Tutorial durch, das ist für den ersten Einstieg ganz gut.
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

@Sussane: Sry, aber da fehlen Grundlagen. Mach doch bitte einmal das offizielle Django Tutorial, dann sollten solche Probleme nicht mehr auftreten.
Antworten