Hilfe bei "messages"

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

Ein bischen was habe ich ja wirklich mal selbst hinbekommen. Jetzt brauche ich aber wieder Hilfe und wollte außerdem wissen, ob ich überhaupt auf dem richtigen Weg bin:
Also so sieht es z.B. aus, wenn die erste (von 10 Aufgaben) erstellt wurde:
Bild

Die Schülerinnen und Schüler haben jetzt 4 Möglichkeiten (wenn man von "abbrechen" absieht): Sie geben die richtige Lösung ein, oder die falsche, sie klicken auf "Lösung" anzeigen oder auf "Hilfe anzeigen". In der (von @whitie) erstellten Version, erfolgt die Rückmeldung über "messages". Diese werden, wie im Screenshot ersichtlich oben angezeigt. Wenn ich das richtig verstanden habe, werden diese als Cookie gespeichert(?)
Ich habe jetzt eigene Tags dazu erstellt:

Code: Alles auswählen

# MESSAGE_TAGS:
RICHTIG = 101
FALSCH = 102
LOESUNG = 103
DREI = 104
HILFE = 105
NEU = 106
Wenn die richtige Lösung eingegeben wurde, soll sich der Hintergrund der Nachricht grün färben, bei falscher rot und ansonsten gelb. Ich dachte, ich könne das jetzt einfach auslesen mit:

Code: Alles auswählen

    {% if messages %} 
        {% for message in messages %}
            {% if level_tag == "FALSCH" %}
                <li style="background-color:rgba(255,0, 0,0.6);">{{ message }}</li>
            {% elif level_tag == "RICHTG" %}
                <li style="background-color:rgba(0, 255, 0,0.6);">{{ message }}</li>
            {% else %}
                <li style="background-color:rgba(255, 255,0.6);">{{ message }}</li>
            {% endif%}
        {% endfor %}
    {% endif %}
... wie ihr sicher schon kundig festgestellt habt, klappt das so nicht (auch nicht mit den Nummern).

Ich habe noch weitere Probleme:
1. Ich brauche immer nur eine Meldung. Wenn ich z.B. auf Lösung klicke, bleibt die letzte Meldung auch noch sichtbar. Entweder müsste nur eine gespeichert werden oder nur der letzte "gelbe" Fund angezeigt werden.
2. Bei den Tags "DREI" (drei falsche Eingaben hintereinander) und "LOESUNG" soll die Aufgabe noch stehen bleiben bis auf weiter geklickt wird. Ich müsste also weiter unten im Template nochmals den level_tag auslesen - die messages werden ja aber oben gelöscht(?)
3 und dann noch: In html gibt es den wunderbaren Filter "floatformat", der dafür sorgt, dass eine Kommazahl nur als solche dargestellt wird, wenn sie auch Nachkommastellen hat. Mich stört die "richtig: 0.0" - gibt es in Python auch so eine schöne Lösung wie in html? Diese Zahl "richtig" ist nämlich fast immer eine Ganzzahl.
Pitwheazle
User
Beiträge: 871
Registriert: Sonntag 19. September 2021, 09:40

Ich habe noch ein bischen rumprobiert. Die verschiedenen message_tags bringen ja nicht wirklich was. Ich werte jetzt einfach den Text in der message aus, das geht genauso gut:

Code: Alles auswählen

    {% for message in messages %}
        {% if 'leider falsch' in message.message %}
            <li style="background-color:rgba(255, 0, 0,0.6);">{{ message }}</li>
        {% elif 'war richtig!' in message.message %}
            <li style="background-color:rgba(0, 255, 0,0.6);">{{ message }}</li>
        {% else %}
            <li style="background-color:rgba(255, 255,0.6);">{{ message }}</li>
        {% endif%}
    {% endfor %}
Die anderen Probleme bestehen aber weiterhin. So wird z.B. wenn ich die erste Lösung eingebe zwar der Text für die richtige Anwort ausgegeben, der gelbe Text für die erste Aufgabe (wie er in meinem Screenshot zu sehen ist) bleibt aber weiterhin bestehen. Ich müsste also irgendwie die letzten messages löschen oder sonstwie dafür sorgen, dass nur die message angezeigt wird, die als letzte erstellt wurde.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Was ist denn `message` für ein Typ. Warum hat message noch ein Attribut message?

Nein, innerhalb einer Nachricht irgendwelchen Text zu suchen, ist sicherlich nicht so toll. Am besten enthält dieser Message-Typ ein Attribut des Nachrichtentyps und ein Property, das für den Typ die passende Farbe liefert:

Code: Alles auswählen

    {% for message in messages %}
        <li style="background-color:{{message.color}};">{{ message }}</li>
    {% endfor %}
Pitwheazle
User
Beiträge: 871
Registriert: Sonntag 19. September 2021, 09:40

Sirius3 hat geschrieben: Donnerstag 24. November 2022, 19:16 Was ist denn `message` für ein Typ. Warum hat message noch ein Attribut message?
Jetzt ist der typ wieder "info" und ich habe ehrlich gesagt keine Ahnung, warum das message.message heißt (das habe ich irgendwo im Internet, möglicherweise hier im Forum aufgegabelt)... aber nur mit message funktioniert es nicht mehr (Mit message.message färbt sich der Hintergrund wie gewünscht, mit messagealleine nicht).
Sirius3 hat geschrieben: Donnerstag 24. November 2022, 19:16 Am besten enthält dieser Message-Typ ein Attribut des Nachrichtentyps und ein Property, das für den Typ die passende Farbe liefert
Also doch, wie oben beschrieben message_tags selbst erstellen? Und wie verpasst man dem Typ eine Farbe?

Ich habe übrigens nach einem Tipp im Internet versucht, die messages zu löschen, bevor ich ein neues erstelle:

Code: Alles auswählen

    storage = messages.get_messages(req)
    for _ in storage:
        pass
    for _ in list(storage._loaded_messages):
        del storage._loaded_messages[0]
    messages.info(req, f'Lösung: {protokoll.loesung[0]}') 
... das klappt auch nicht.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Kein Ahnung, was Du da machst. Du zeigst hier ja nie funktionierende Code-Teile mit Beispieldaten, die man einfach selbst ausführen könnte.

Nach langer Suche bin ich schließlich darauf gekommen, dass Du anscheinend django.contrib.messages benutzt.

Die Messages mußt Du gar nicht löschen, weil die automatisch gelöscht werden, sobald Du sie einmal angezeigt hast. Auf _-Attribute darf man nicht direkt zugreifen. Wenn diese Art Messages nicht zu Deinem Anwendungsfall passt, mußt Du Dir was anderes suchen, oder selbst programmieren.

Gedacht ist es, die Tags für die Anzeige zu benutzen:

Code: Alles auswählen

    {% for message in messages %}
        <li class="message {{message.tags}}">{{ message }}</li>
    {% endfor %}[/html]
Und dann entsprechende CSS-Regeln für li.message.info, li.message.error etc. definieren.
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Du musst deine eigenen Level schon korrekt angeben. Laut Doku könnte das so aussehen:

Code: Alles auswählen

# settings.py
RICHTIG = 101
FALSCH = 102
LOESUNG = 103
DREI = 104
HILFE = 105
NEU = 106

MESSAGE_TAGS = {
    RICHTIG: 'green',
    FALSCH: 'red',
    # usw.
}
So könntest du die Farbe direkt im HTML benutzen. message.tags ist die Farbe und message.level die Zahl.

Da ist aber nicht sehr schön, da du jetzt überall die Konstanten aus der settings.py importieren musst, um nicht mit magischen Zahlen zu arbeiten. Zusätzlich heisst das Attribut, das die Farben enthält, nicht umsonst tags (Mehrzahl). Es ist eigentlich für CSS-Klassen gedacht und kann auch mehr als einen Tag enthalten.

Meine Lösung wäre, eine eigene Datei für die Konstanten (z. B. message_utils.py) und die Tags auf CSS-Klassen abbilden. Etwa so:

Code: Alles auswählen

# message_utils.py
RICHTIG = 101
FALSCH = 102
LOESUNG = 103
DREI = 104
HILFE = 105
NEU = 106

# settings.py
from . import message_utils
MESSAGE_TAGS = {
    message_utils.RICHTIG: 'richtig',
    message_utils.FALSCH: 'falsch',
    # usw.
}

# views.py
from django.contrib import messages
from . import message_utils

def index(request):
    messages.add_message(request, message_utils.FALSCH, 'Hier dein Text')
    ...

Den Template- und den CSS-Code überlasse ich mal dir ;-)

Viele Grüße
Whitie

P. S. @Sirius3 es handelt sich um das Messages Framework von Django.

Edit: Hat sich wohl mit Sirius Antwort überschnitten 8)
Pitwheazle
User
Beiträge: 871
Registriert: Sonntag 19. September 2021, 09:40

Sirius3 hat geschrieben: Donnerstag 24. November 2022, 20:17 Kein Ahnung, was Du da machst. Du zeigst hier ja nie funktionierende Code-Teile mit Beispieldaten, die man einfach selbst ausführen könnte.
Nach langer Suche bin ich schließlich darauf gekommen, dass Du anscheinend django.contrib.messages benutzt.
@sirius3: Sorry dafür. Ich war davon ausgegangen, dass (außer mir) jeder diese messages kennt und weiß, dass die Nutzung dieses "contrib/messages/]Messages Framework"s jedem (außer mir) geläufig ist. Ich habe das ja einfach von @whitie übernommen und zwischenzeitlich versucht es mithilfe der Docs zu verstehen.
Möglicherweise ist ja der Aufbau meines Projekts zu kompliziert. Ich weiß halt nie, wie ich funktionierened Codeteile herausschnippseln kann, da meine Probleme in verschiednenen Codeteilen verteilt sind. Ich habe mir Mühe gegeben, meinen Code zu kommentieren und vielleicht wäre es gut, wenn mal jemand einen Blick drauf werfen könnte bevor ich ihn hochlade. (Möglicherweise benötigt man dann aber gute Nerven, weil ich das u.U. unkonventionell zusammengebaut habe.)

@whitie: Leider überfordert mich deine Anleitung intellektuell (ich bin halt nur ein linearer Basic Pfuscher.). Zwischenzeitlich funktioniert mein oben vorgestellter Code, in dem ich den Inhalt des message Textes auslese. Besteht da jetzt irgendein Nachteil, dass ich es bei den sechs Codezeilen belasse?
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Du kannst es so lassen. Fühlt sich halt wie ein kleiner Hack an. Ich würde es dann aber noch ein wenig robuster machen.

Code: Alles auswählen

{% for message in messages %}
        {% if 'falsch' in message.message|lower %}
            <li style="background-color:rgba(255, 0, 0,0.6);">{{ message }}</li>
        {% elif 'richtig!' in message.message|lower %}
            <li style="background-color:rgba(0, 255, 0,0.6);">{{ message }}</li>
        {% else %}
            <li style="background-color:rgba(255, 255,0.6);">{{ message }}</li>
        {% endif%}
{% endfor %}
Also Leerzeichen raus und Text vorsichtshalber in Kleinbuchstaben umwandeln. Für die Farben würde ich mir trotzdem CSS-Klassen machen, falls man sie noch an anderer Stelle braucht.

Aber wie schon geschrieben, genau dafür kann man eigene Konstanten definieren (wie in der Django Doku gezeigt). Einmal vernünftig gemacht, spart es wahrscheinlich Zeit und Nerven bei der Pflege/Erweiterung.

Viele Grüße
Whitie
Antworten