Bedingung "wenn Monat = .." in template

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

Code: Alles auswählen

Monat:    {% now "m"  %}  

geht wunderbar

Code: Alles auswählen

{% if now "m" in [01, 06, 07] %} 
geht nicht.
Benutzeravatar
__blackjack__
User
Beiträge: 13122
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Pitwheazle: ``now`` ist ja auch ein Template-Tag, wie ``if``, das ist so etwas wie ein Schlüsselwort in Python und muss an erster Stelle stehen. In der Django-Dokumentation zu dem ``now``-Tag steht dann aber im Grunde schon ein Lösungsansatz, weil dieses Tag sein Ergebnis auch an einen Namen binden kann, den man dann an anderer Stelle im Template verwenden kann um den Wert zu verwenden. Wobei der Wert keine Zahl ist.

Und 01, 06, und 07 müssten eigentlich auch zu einem Syntaxfehler führen, weil bei Dezimalzahlen keine führenden 0en erlaubt sind:

Code: Alles auswählen

In [87]: 01
  Input In [87]
    01
     ^
SyntaxError: leading zeros in decimal integer literals are not permitted; use an 0o prefix for octal integers
Das ging früher mal, da hat eine führende 0 eine Oktalzahl gekennzeichnet, was man heute explizit mit ``0o`` machen muss, und nicht mehr einfach nur mit einer 0.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Hurra, danke, da habe ich sogar mal was in der Dokumentation verstanden und es funktioniert ... fast:

Code: Alles auswählen

    {% now "m" as monat%}
    {% if monat == "10"  %}
    Hallo!
    {% endif %}
geht mit dem Oktober, ich brauche aber den Januar, Juni und Juli. Jetzt muss ich, wegen string, die 0 ergänzen, oder? Aber nicht die Null ist das Problem, sondern die Liste:

Code: Alles auswählen

{% if monat in ["01", "06", "07"] %} 
will nicht, muss ich hier wirklich mit "or" arbeiten?
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Du könntest statt "m" auch "n" verwenden, dann hast du keine führenden Nullen (ist bei Zeichenketten aber eigentlich egal). Was hindert dich daran, deine Liste aus der View-Funktion zu übergeben?

Code: Alles auswählen

def mein_view(request):
    ...
    return render(request, template, {'monate': ['1', '6', '7']})

# im Template
{% now "n" as monat %}
{% if monat in monate %}
Viele Grüße
Whitie

Edit: Du könntest das ganze natürlich auch komplett im View machen und nur ein Flag ins Template geben, ob einer der drei Monate ist.

Code: Alles auswählen

from django.utils import timezone

# im View
is_special_month = timezone.now().month in [1, 6, 7]
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Whitie hat geschrieben: Samstag 15. Oktober 2022, 07:56 Was hindert dich daran, deine Liste aus der View-Funktion zu übergeben?
Da ergibt sich ein neues Problem: Ich brauche diese Monatsoption auch im Login ... und da habe ich keine Ahnung, wo das zugehörige view zu finden ist. Das ist ja irgendwie in Django eingebaut - kann ich das irgendwie ändern?
Und dann habe ich noch ein Problem: So wie ich mir das dachte, klappt das nicht.
Zunächst zur Erklärung: In meinem bestehenden Rechentrainer bekommen die SuS Noten auf ihre Arbeit und bei mir konnten sie mit dieser Note u.U. ihre Zeugnisnote verbessern. Im Januar und Juli (oder auch schon im Juni - bei frühen Ferien) ist das mit den Zeugnisnoten meistens schon gelaufen. Also hatte ich die Option eingebaut, dass die Kids schon mal für das nächste Schuljahr vorarbeiten können.
Mein Registrierungstemplate sieht jetzt so aus:Bild
(Jetzt steht natürlich "Oktober" statt z.B. Januar)
mein Template:

Code: Alles auswählen

{% block content %}
  <h2>Registrieren</h2>
  <form method="post" action="{% url 'registrieren' %}">
    {% csrf_token %}
    {{ form.as_p }}
    <h2>Achte hier unten auf die richtige Schreibweise - du kannst deinen Namen nach dem Speichern nicht mehr ändern!</h2>
    {{ profile_form.as_p }}
    {% now "m" as monat%}
      {% if monat == "10" or monat == "06" or monat == "07"  %}
      <h2>Wir haben jetzt {% now "F" %} - bald gibt es Zeugnisse. Sollen deine Aufgaben, die du ab jetzt machst, schon für das nächste Schulhalbjahr zählen?</h2>
      Diese Wahl kannst du nicht rückgängig machen. Bestätige sie also bitte, indem du hier "ja" eingibst:
        <form>
        <label> neues Schulhalbjahr? </label> 
        <input id = "neu" type="text">
        </form>  
    {% endif %}
    <input type="submit" value="Registrieren">
  </form>
{% endblock %}
und der/das view:

Code: Alles auswählen

def registrieren(req):
    if req.method == 'POST':
        form = Register_Form(req.POST)
        profile_form = Schueler_Profil_Form(req.POST)
        if  form.is_valid and profile_form.is_valid():
            #user.email = form.cleaned_data['Email']
            user = form.save()
            profile = profile_form.save(commit=False)
            kurs = profile_form.cleaned_data['kurs']
            if kurs == "i":
                profile.stufe = 0
            else:            
                jg = profile_form.cleaned_data['jg']
                stufe_liste = [2,4,12,20,26,32,50]
                profile.stufe = stufe_liste[jg-5] 
            if kurs in ["Y","R","E","B"]:
                profile.stufe +=1
            sj, hj = name_hj()
            #neu = ["neu"]
            #print(neu)
            profile.sj = sj
            profile.hj = hj
            profile.user = user
            profile.save()
            username = form.cleaned_data['username']
            password = form.cleaned_data['password1']
            user = authenticate(username=username, password=password)
            login(req, user)
            group = Group.objects.get(name='Schüler')
            user.groups.add(group)
            return redirect('kategorien')
    else:
        form = Register_Form()
        profile_form = Schueler_Profil_Form() 
    context = {'form' : form, 'profile_form' : profile_form} 
    return render(req, 'registration/registrieren.html', context)
Die Eintragungen von username, passwort, vorname, nachname usw. wird direkt in die Datenbank vorgenommen. Die optionale Abfrage nach "neues Schuljahr" benötige ich nur im view. Da muss ich doch nicht extra eine form erstellen, oder? Aber wie frage ich den Eintrag ab und außerdem, nach der Ergänzung der "neues Schuljahr" Abfrage passiert nix, wenn ich auf registrieren klicke (ob ich Django jeweils alleine beherrsche?)
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Das Einfachste wäre es wohl, die Abfrage auf eine neue Seite auszulagern. Oder du befasst dich mal mit Javascript.

Einfache Lösung:

Code: Alles auswählen

def registrieren(req):
    if req.method == 'POST':
        form = Register_Form(req.POST)
        profile_form = Schueler_Profil_Form(req.POST)
        if  form.is_valid and profile_form.is_valid():
            # Hier dein ganzer Code
            if timezone.now().month in [1, 6, 7]:
                return redirect('abfrage_neues_schuljahr')
            else:
                return redirect('kategorien')
    else:
        form = Register_Form()
        profile_form = Schueler_Profil_Form() 
    context = {'form' : form, 'profile_form' : profile_form} 
    return render(req, 'registration/registrieren.html', context)
Damit könntest du die Logik in einen eigenen View auslagern und es bleibt übersichtlich.

Viele Grüße
Whitie

Edit: Noch einfacher ist es vielleicht, die Abfrage im Formular zu lassen (ohne eigenes form Tag) und das Ergebnis vorher auszulesen.

Code: Alles auswählen

{% block content %}
  <h2>Registrieren</h2>
  <form method="post" action="{% url 'registrieren' %}">
    {% csrf_token %}
    {{ form.as_p }}
    <h2>Achte hier unten auf die richtige Schreibweise - du kannst deinen Namen nach dem Speichern nicht mehr ändern!</h2>
    {{ profile_form.as_p }}
    {% now "m" as monat%}
      {% if monat == "10" or monat == "06" or monat == "07"  %}
      <h2>Wir haben jetzt {% now "F" %} - bald gibt es Zeugnisse. Sollen deine Aufgaben, die du ab jetzt machst, schon für das nächste Schulhalbjahr zählen?</h2>
      Diese Wahl kannst du nicht rückgängig machen. Bestätige sie also bitte, indem du hier "ja" eingibst:
        <label> neues Schulhalbjahr? </label> 
        <input id="neu" name="neu" type="text">
    {% endif %}
    <input type="submit" value="Registrieren">
  </form>
{% endblock %}

Code: Alles auswählen

def registrieren(req):
    if req.method == 'POST':
        neues_halbjahr = req.POST.get('neu', 'nein')
        form = Register_Form(req.POST)
        profile_form = Schueler_Profil_Form(req.POST)
        if  form.is_valid and profile_form.is_valid():
            # Dein ganzer Code
            if neues_halbjahr.lower() == 'ja':
                # Hier das Ergebnis verarbeiten
            return redirect('kategorien')
    else:
        form = Register_Form()
        profile_form = Schueler_Profil_Form() 
    context = {'form' : form, 'profile_form' : profile_form} 
    return render(req, 'registration/registrieren.html', context)
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Das geht prima!
Und wieder was dazugelernt!
... aber nochmal die Frage: Wenn ich das auch beim Einloggen ergänzen will, müsste ich die Eingabe auch dort im entsprechenden view abfragen - aber wie?

Nachtrag:
Ansonsten könnte ich das natürlich auf meiner Aufgabenseite nach der Userauthentifizierung einfügen, dann würde das aber bei jeder einzelnen Aufgabenerstellung abgefragt, dass macht m.E. nicht so viel Sinn.

Noch ein Nachtrag:
Irgendjemand hat hier geschrieben, während des Schreibens käme manchmal die Erkenntnis - hier war es nach dem Herunterfahren: wahrscheinlich muss ich den/das view selbst schreiben.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Whitie hat geschrieben: Sonntag 16. Oktober 2022, 06:20 Edit: Noch einfacher ist es vielleicht, die Abfrage im Formular zu lassen (ohne eigenes form Tag) und das Ergebnis vorher auszulesen.
Ich habe das mit dem Login schon fast hinbekommen - aber noch nicht ganz. Wahrscheinlich habe ich das mit "... Ergebnis vorher auszulesen" noch nicht verstanden.

Code: Alles auswählen

def login(req):
    if req.method == 'POST':
        neues_halbjahr = req.POST.get('neu', 'nein')
        form = Login_Form(req.POST)
        if  form.is_valid ():
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']
            user = authenticate(req, username=username, password=password)
            if user is not None:
                login(req, user)               
                return redirect('kategorien')
            else:
                print("kein user!")
        if neues_halbjahr.lower() == 'ja':
            print("neu") 
        else:
            print("nicht neu")  
    else:
        form = Login_Form()
        context = {'form' : form} 
    return render(req, 'registration/login.html', context)
.... weder wird "neu" noch "nicht neu" angezeigt.
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Weil du vorher schon den redirect machst. Gib doch mal falsche Anmeldedaten ein, oder pack die if-Abfrage (if neues_halbjahr...) vor if user...
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Whitie hat geschrieben: Sonntag 16. Oktober 2022, 14:16 Weil du vorher schon den redirect machst. ... pack die if-Abfrage (if neues_halbjahr...) vor if user...
Ja, jetzt klappt "neu/nicht neu", jetzt klappt aber das login nicht mehr: "login() takes 1 positional argument but 2 were given"

Code: Alles auswählen

def login(req):
    if req.method == 'POST':
        neues_halbjahr = req.POST.get('neu', 'nein')
        form = Login_Form(req.POST)
        if  form.is_valid ():
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']
            user = authenticate(req, username=username, password=password)
            if neues_halbjahr.lower() == 'ja':
                print("neu") 
            else:
                print("nicht neu")  
            if user is not None:
                login(req, user)               
                return redirect('kategorien')
            else:
                print("kein user!")
        return redirect('kategorien')            
    else:
        form = Login_Form()
        context = {'form' : form} 
    return render(req, 'registration/login.html', context)
... wobei ich wieder peinlicherweise zugeben muss, dass ich nicht genau weiß was "req" in login(req, user) macht - übergibt das nur "POST"?
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Du darfst deine eigene Funktion nicht login nennen :D Die ruft er jetzt auf.
Das return redirect... muss eine Einrückungsebene tiefer.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Ach, wie du das immer aus der Ferne erkennen kannst! Prima! Allerdings ist mir aufgefallen, dass bestimmte Änderungen nicht immer sofort wirksam werden - genauer gesagt, für mich scheint es so. Ich habe die Namen des views und des templates geändert und auch die Links dahingehend angepasst. Ich bekam zunächst aber die Fehlermeldung, dass "registration/login.html" nicht gefunden wurde - klar, ich habe es ja aus "registration" rausgenommen und in "einloggen.html" gepackt. ich musste das mehrmals aufrufen und mehrmals speichern, irgendwann klappte es dann. Liegt das am cache oder bin ich wieder zu dusselig?

Jetzt aber ein neues Problem zu dem mir kein einfacher Weg einfällt:
Die Frage, ob die Aufgaben schon für das nächste Schulhalbjahr gezählt werden sollen, ist überflüssig, wenn der Nutzer dies schon einmal bejaht hat und sein Profil dementsprechend geändert wurde. Ich müsste also, bevor ich das Template mit der Frage aufrufe zunächst feststellen, ob das Schüerprofil schon dementsprechend geändert wurde und dementsprechend diese Frage nicht mehr anzeigen, das kann ich aber nicht, da zu dem Zeitpunkt der user sich noch nicht eingeloggt hat und daher nicht bekannt ist. Gehe ich recht in der Annahme, dass ich demzufolge zwei templates erstellen muss, oder hast du/habt ihr dazu eine andere geniale Idee?
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Ja, dann würde ich eine zweite Stufe einbauen. Im login-View feststellen, ob die Frage schon beantwortet wurde und dann den redirect entweder auf die Frage oder eben direkt zu den Kategorien.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Whitie hat geschrieben: Montag 17. Oktober 2022, 12:14 Ja, dann würde ich eine zweite Stufe einbauen. Im login-View feststellen, ob die Frage schon beantwortet wurde und dann den redirect entweder auf die Frage oder eben direkt zu den Kategorien.
Ja , das habe ich tatsächlich hinbekommen. Allerdings habe ich jetzt schon die nächste Frage:
Der user wird ja normalerweise automatisch eingeloggt. Ich müsste also eigentlich mein "neues Schuljahr" template aufrufen, wenn der user eingeloggt wird und nicht wenn er/sie sich selbst einloggt. Wo/wann passiert das, kann ich mich da einhängen?

Mein Programm schreitet ja voran und ich muss mich mal langsam mit der Veröffentlichung beschäftigen. Ich habe auch schon mal in entsprechende Tutorien reingeschaut, in keinem sind Cookies, Impressum und Datenschutz ein Thema ... und das mit der automatischen Anmeldung ist ja schon mal ein Cookie. Hat da jemand Ideen, wo ich mich da informieren kann?
Antworten