ich brauche Hilfe beim Auslesen von forms.DateField

Django, Flask, Bottle, WSGI, CGI…
Antworten
Pitwheazle
User
Beiträge: 1045
Registriert: Sonntag 19. September 2021, 09:40

Ich habe eine Anfrage, ob ich nicht eine von- bis-Datum Abfrage in meine Übersicht einbauen kann. Das gelingt mir noch nicht.
Bisher gibt es eine ChoiceField Abfrage die funktioniert:
form:

Code: Alles auswählen

class ProtokollFilter_Gruppe(forms.Form):
    auswahl = forms.ChoiceField(label='', choices=[("Halbjahr",'aktuelles Halbjahr'),('Woche','Woche'), ("Schuljahr",'aktuelles Schuljahr'), ('heute','heute'), ("all",'Alle Aufgaben'),("next",'nächstes Halbjahr'), ])
Template:

Code: Alles auswählen

    <form action="{% url 'gruppe_uebersicht' gruppe_id %}" method="POST">
        {% csrf_token %}
        <h2 style= "text-align: left;"> Zeitraum: 
            <button type="button">
                {{form_filter.auswahl}}
            </button type="button">            
            <button type="button">
                <input name="filter" type="submit" value="anwenden">
            </button type="button">
        </h2>
    </form>
view:

Code: Alles auswählen

def gruppe_uebersicht(req, gruppe_id):
...
    form_filter = ProtokollFilter_Gruppe
...
    if req.method == 'POST':
        auswahl = form_filter(req.POST)
        filter = auswahl.fields['auswahl'].choices
        auswahl_liste = dict(filter)
        if auswahl.is_valid(): 
            auswahl = auswahl.cleaned_data['auswahl']
            protokoll_zeitraum = protokoll_zeit_filter(protokoll_gruppe, auswahl)
            wahl = auswahl_liste[auswahl]
    else:
        wahl = "aktuelles Halbjahr"
...
    context={'wahl': wahl, 'form_filter': form_filter,}  
    return render(req, 'lehrer/gruppe_uebersicht.html', context)
Ich habe jetzt einfach versucht, das mit dem Datum-Auswahl-Feld genauso zu machen:
form:

Code: Alles auswählen

class Start_Datum(forms.Form):
    aufgaben_seit = forms.DateField(label="", widget = forms.SelectDateWidget())
Template:

Code: Alles auswählen

    <form action="{% url 'gruppe_uebersicht' gruppe_id %}" method="POST">
        {% csrf_token %}
        <h2 style= "text-align: left;"> Zeitraum: 
            <button type="button">
                {{{{startdatum}}}}
            </button type="button">            
            <button type="button">
                <input name="filter" type="submit" value="anwenden">
            </button type="button">
        </h2>
    </form>
view:

Code: Alles auswählen

       start_filter = Start_Datum
       startdatum = start_filter(req.Post)
        if startdatum.is_valid():
            startdatum = startdatum.cleaned_data['aufgaben_seit']
            print(startdatum)

Code: Alles auswählen

startdatum = start_filter(req.Post)
funktioniert so nicht - was muss ich da ändern?
Das Datumfeld wird angezeigt aber wenn ich "anwenden" anklicke, kommt der Fehler:

Code: Alles auswählen

 	
'WSGIRequest' object has no attribute 'Post'

Request Method: 	POST
Request URL: 	http://localhost:8000/gruppe_uebersicht/2/
Django Version: 	5.0.7
Exception Type: 	AttributeError
Exception Value: 	

'WSGIRequest' object has no attribute 'Post'

Exception Location: 	D:\Dropbox\RechentrainerApp\rechentrainer.app\accounts\views.py, line 509, in gruppe_uebersicht
Raised during: 	accounts.views.gruppe_uebersicht
Python Executable: 	C:\Users\Pit\AppData\Local\Programs\Python\Python310\python.exe
Python Version: 	3.10.1
Python Path: 	

['D:\\Dropbox\\RechentrainerApp\\rechentrainer.app',
 'C:\\Users\\Pit\\AppData\\Local\\Programs\\Python\\Python310\\python310.zip',
 'C:\\Users\\Pit\\AppData\\Local\\Programs\\Python\\Python310\\DLLs',
 'C:\\Users\\Pit\\AppData\\Local\\Programs\\Python\\Python310\\lib',
 'C:\\Users\\Pit\\AppData\\Local\\Programs\\Python\\Python310',
 'C:\\Users\\Pit\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages']

Server time: 	Sun, 02 Mar 2025 16:30:48 +0100
Traceback Switch to copy-and-paste view

    C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\exception.py, line 55, in inner

                        response = get_response(request)

         …
und unter "request information"

Code: Alles auswählen

Variable 	Value
csrfmiddlewaretoken 	

'DEOEvnIXaF7kY80pe3NzhqHv5eUbJvi8NQle1yAiJtbPqlNxcuVOMIocOrRKwfIb'

aufgaben_seit_day 	

'1'

aufgaben_seit_month 	

'1'

aufgaben_seit_year 	

'2025'

filter 	

'anwenden'
Zuletzt geändert von Pitwheazle am Sonntag 2. März 2025, 16:53, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 18185
Registriert: Sonntag 21. Oktober 2012, 17:20

Im einen Fall schreibst Du `req.POST` und im anderen `req.Post`. Du solltest wirklich mal lernen, wie man Fehlermeldungen interpretiert.
Pitwheazle
User
Beiträge: 1045
Registriert: Sonntag 19. September 2021, 09:40

Manchmal sind es nur die Kleinigkeiten - Ich bin einfach schlampig! Danke!
Benutzeravatar
noisefloor
User
Beiträge: 4118
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

kann ja passieren. Aber der _wirklich_ entscheidende Satz in der Antwort von @Sirius3 ist: "Du solltest wirklich mal lernen, wie man Fehlermeldungen interpretiert." Im gegebenen Fall steht da ja auch sehr eindeutig drin, warum der Fehler geworfen wird. Und wenn du dir alle Attributen und Methoden von einem Objekt anzeigen lassen willst, dann geht das immer mit `dir(NAME_DES_OBJEKTS)`. Also überall in Python, das ist nicht Django-spezifisch.

Gruß, noisefloor
Pitwheazle
User
Beiträge: 1045
Registriert: Sonntag 19. September 2021, 09:40

So einfach ist das nicht. Ich erwarte immer, dass es etwas kompliziertes ist und ich in diesem Fall nicht weiß, dass das Datum anders funktioniert und ich möglicherweise drei Abfragen für Tag, Monat und Jahr getrennt machen muss oder irgenwas Grundlegendes und dass diese Form halt mit "Post" nicht umgehen kann. Ihr seht sowas gleich. Für mich müsste die Fehlermeldung dann schon 'WSGIRequest' object has no attribute 'Post but has an attribute POST' - heißen - das hätte dann sogar ich verstanden.
Benutzeravatar
sparrow
User
Beiträge: 4475
Registriert: Freitag 17. April 2009, 10:28

Und deshalb der Hinweis, dass du lernen musst, wie man die Fehlermeldungen liest.
Da steht alles, wa du brauchst. Inklusive der Zeile, in der die Ausnahme auftritt (views.py, line 509, in gruppe_uebersicht). Was ein WSGIrequest ist, solltest du nach ~4 Jahren Python wissen. Und was ein Attribut ist auch. Und von da ist der Weg zu Dokumentation nicht weit.
Pitwheazle
User
Beiträge: 1045
Registriert: Sonntag 19. September 2021, 09:40

Jetzt funktioniert es ... fast:
meine forms:

Code: Alles auswählen

class ProtokollFilter_Gruppe(forms.Form):
    auswahl = forms.ChoiceField(label='', choices=[("Halbjahr",'aktuelles Halbjahr'),('Woche','Woche'), ("Schuljahr",'aktuelles Schuljahr'), ('heute','heute'), ("all",'Alle Aufgaben'),("next",'nächstes Halbjahr'),("individuell",'individuelle Auswahl'), ])

class Start_Datum(forms.Form):
    aufgaben_seit = forms.DateField(label="", widget = forms.SelectDateWidget())

class End_Datum(forms.Form):
    aufgaben_bis = forms.DateField(label="", widget = forms.SelectDateWidget())
mein Template:

Code: Alles auswählen

    <form action="{% url 'gruppe_uebersicht' gruppe_id %}" method="POST">
        {% csrf_token %}
        <h2 style= "text-align: left;"> Zeitraum: 
            {% if "individuelle Auswahl" in wahl %}
                oder von:
                <button type="button">
                    {{startdatum}}
                </button type="button">
                bis:
                <button type="button">
                    {{enddatum}}
                </button type="button">
            {% else %}
                <button type="button">
                    {{form_filter.auswahl}}
                </button type="button">
            {% endif %}
            <button type="button">
                <input name="filter" type="submit" value="anwenden">
            </button type="button">
        </h2>
    </form>
mein view:

Code: Alles auswählen

    if req.method == 'POST':
        start_datum = Start_Datum(req.POST)
        end_datum = End_Datum(req.POST)
        print("Ende: ", end_datum)
        auswahl = form_filter(req.POST)
        filter = auswahl.fields['auswahl'].choices
        auswahl_liste = dict(filter)
        if auswahl.is_valid(): 
            auswahl = auswahl.cleaned_data['auswahl']
            protokoll_zeitraum = protokoll_zeit_filter(protokoll_gruppe, auswahl)
            wahl = auswahl_liste[auswahl]
        elif start_datum.is_valid() and end_datum.is_valid:
            start = start_datum.cleaned_data['aufgaben_seit']
            ende = end_datum.cleaned_data['aufgaben_bis']
            protokoll_zeitraum =  protokoll_gruppe.filter(start__date__gte = start, start__date__lte = ende)
            wahl = start.strftime("%d.%m.%y") + " bis " + ende.strftime("%d.%m.%y")
Beim ersten Aufruf kann die Lehrkraft "individuelle Auswahl" auswählen. Es kommt eine Auswahlmöglichkeit mit zwei Datumsfelder und die Auswahl funktioniert dann auch wie gewünscht.
Das erste Problem verstehe ich gar nicht. Wenn ich die Zeile

Code: Alles auswählen

print("Ende: ", end_datum)
weglasse kommt der Fehler

Code: Alles auswählen

'End_Datum' object has no attribute 'cleaned_data'
Ich habe jetzt noiesfloors Tipp befolgt (den habt ihr mir schon mal gegeben :( ).
noisefloor hat geschrieben: Sonntag 2. März 2025, 17:55 Und wenn du dir alle Attributen und Methoden von einem Objekt anzeigen lassen willst, dann geht das immer mit `dir(NAME_DES_OBJEKTS)`. Also überall in Python, das ist nicht Django-spezifisch.
Wenn ich mir "Start_Datum" und "End_Datum" anzeigen lasse, haben sie beide kein "cleaned_data". Trotzdem funktioiert "cleaned_data bei "Start_Datum" und auch bei "End_Datum", bei letzterem aber nur, wenn ich vorher " print("Ende: ", end_datum)" aufrufe.
Und noch eine Frage: Die Jahreszahlen in den Datums_Auswahl_Fenstern fangen erst bei 2025 an, wie bringe ich die dazu, dass sie auch 2024 anzeigen?
Benutzeravatar
noisefloor
User
Beiträge: 4118
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Ich sehe gerade nicht, wo der Fehler im gezeigten Code auftreten soll... Bitte mal den vollen Stack Trace hier posten.

Gruß, noisefloor
Pitwheazle
User
Beiträge: 1045
Registriert: Sonntag 19. September 2021, 09:40

Ich bin wirklich unfähig - aber ich habe den Fehler gefunden: Ich habe () hinter "datum.is_valid" vergessen :cry:

Code: Alles auswählen

elif start_datum.is_valid() and end_datum.is_valid():
Hat trotzdem jemand einen Tipp wie ich die Datumsauswahl um das letzte Jahr ergänze?
Pitwheazle
User
Beiträge: 1045
Registriert: Sonntag 19. September 2021, 09:40

Vielleicht interessiert es noch. Ich habe rausbekommen, wie ich die Jahreszahlen vorgebe und das aktuelle Datum einsetze:

Code: Alles auswählen

class Start_Datum(forms.Form):
    aufgaben_seit = forms.DateField(label="", widget = forms.SelectDateWidget(years=range(2024, 2031)), initial=datetime.today())
... aber das wusstet ihr wahrscheinlich schon.
Benutzeravatar
noisefloor
User
Beiträge: 4118
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Es steht wahrscheinlich irgendwo in einer Doku ;-)

Bzgl. des Endedatums: würde ich so nicht mehr, sondern mit Hilfe des `datetime.date` Moduls das aktuelle Jahr bestimmt, das eine eine Variable binden und die beim Endwert einsetzen. Vorteil: du musst den Code an der Stelle nicht mehr anfassen. Im gezeigten Fall musst du spätestens 2032 an den Code wieder ran. Abgesehen davon ist es IMHO verwirrend, wenn man Aufgaben abfragen kann, die in der Zukunft liegen. Nichts gegen die Schüler von heute, aber IMHO sind die wenigsten so "ahead of time", dass das relevant wäre ;-)

Gruß, noisefloor
Pitwheazle
User
Beiträge: 1045
Registriert: Sonntag 19. September 2021, 09:40

Danke für den Hinweis - prima!
Antworten