Ist Django für mein Projekt geeignet?

Django, Flask, Bottle, WSGI, CGI…
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

1. "kategorien = []" ... erstellt eine leere Liste
2. Die Schleife ruft nacheinander alle Elemente in "Kategorie" auf
3. "zaehler = " ... sucht die Einträge in Zaehler in denen der User und die Kategorie übereinstimmt (und findet in diesem Falle drei)
4. "kategorien.append(kategorie,zaehler) ... hängt in der Liste ... was an? Und warum wird die erste Klammer erst hier geschlossen?
5. ... und, wenn ich das richtig sehe, kann ich auch " 'zaehler': zaehler," in "return ..." weglassen

6. und was genau macht "zeile" und "zaehler..." in "{% for zeile, zaehler in kategorien %}"?
1. ja
2. ja (du könntest hier mit .order_by(...) noch die Reihenfolge beeinflussen)
3. jein (ich hoffe er findet pro Schleifendurchlauf einen Zaehler und insgesamt dann drei)
4. Da fehlt ein paar Klammern bei dir. kategorien.append((kategorie, zaehler)) hängt einen Tupel mit 2 Elementen an die Liste an. So hast du die Kategorie und die passenden Ergebnisse des Benutzer zusammen in einer Datenstruktur.
5. ja, kannst du weglassen. Es ist eh nur der zaehler aus dem letzten Schleifendurchlauf.
6. Da wird bei jedem Durchlauf der entsprechende Tupel (kategorie, zaehler) entpackt und an zwei Namen gebunden. So kannst du einfacher zugreifen.

Edit: Fragen eingefügt, da Post auf neuer Seite ;-)
Pitwheazle
User
Beiträge: 869
Registriert: Sonntag 19. September 2021, 09:40

Vielen Dank! Jetzt habe ich auch (hoffentlich) das mit den Tupeln gelernt (Mit denen hatte ich schon Probleme in der Vorlesung "Lineare Algebra" bei Professor Osorio)
Aber was neues:

Code: Alles auswählen

text = "Du hast für {0:.2f}€ eingekauft und bezahlst mit einem {1:.0f}€ Schein".format(2.20, 5).replace('.', ',') + ". \nWieviel Wechselgeld erhälst du?"
print(text)
"print" macht wunderbar einen Zeilenwechsel. Wenn ich das aber in meine form auf der HTML Seite einfüge klappt das nicht und ebenso ist es mir nicht gelungen einen Zeilenwechsel in den messages einzufügen - geht das nicht?
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Das dürfte interpretiertes html sein. Da sollte mit <br> ein Zeilenumbruch erreicht werden.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Pitwheazle: Das mit dem `replace()` funktioniert nicht mehr wenn im normalen Text Punkte vorkommen. Zum Beispiel bei Abkürzungen, oder an Satzenden.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Pitwheazle
User
Beiträge: 869
Registriert: Sonntag 19. September 2021, 09:40

__blackjack__ hat geschrieben: Dienstag 7. Juni 2022, 18:45 @Pitwheazle: Das mit dem `replace()` funktioniert nicht mehr wenn im normalen Text Punkte vorkommen. Zum Beispiel bei Abkürzungen, oder an Satzenden.
Nun ja, es funktioniert schon, nur werden halt auch erwünschte Punkte ersetzt. Dadurch dass ich den Text unterteilt habe klappt das schon und ansonsten hatte ich einfach die erwünschten Punkte durch Semikolon ersetzt und dann die Semikolons durch Punkte. :)
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Pitwheazle: Wenn man so gruselige Hacks mag…
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Formatier die Zahlen erst im Template, dann kümmert sich Django um die korrekten Zeichen.

Code: Alles auswählen

{{ wert|floatformat:2 }}
Siehe hier

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

sparrow hat geschrieben: Dienstag 7. Juni 2022, 18:11 Das dürfte interpretiertes html sein. Da sollte mit <br> ein Zeilenumbruch erreicht werden.
Also mit

Code: Alles auswählen

". <br>Wieviel Wechselgeld erhälst du?" 
geht es auch nicht
Whitie hat geschrieben: Dienstag 7. Juni 2022, 22:21 Formatier die Zahlen erst im Template, dann kümmert sich Django um die korrekten Zeichen.

Code: Alles auswählen

{{ wert|floatformat:2 }}
Ich habe aber ständig andere Stellen zum Runden. Hier mein derzeitiger Code nur fürs Ergänzen:

Code: Alles auswählen

       typ = random.randint(typ_anf, typ_end)        
        if typ == 1:                                        #Wechselgeld
            NOTES = [2, 5, 10, 20, 50, 100]
            zahl1 = random.randint(5, 5950)/100
            start = 0
            while True:
                if NOTES[start] > zahl1:
                    break
                start += 1
            zahl2 = (random.choice(NOTES[start:]))
            if zahl2 > 2:
                text = "Du hast für {0:.2f}€ eingekauft und bezahlst mit einem {1:.0f}€ Schein".format(zahl1, zahl2).replace('.', ',')
            else:
               text = "Du hast für {0:.2f}€ eingekauft und bezahlst mit 2€ ".format(zahl1, zahl2).replace('.', ',')  
            text = text + ". Wieviel Wechselgeld erhälst du?"  
            proText = "Wechselgeld: {0:.0f}€ - {1:.2f}€".format(zahl2, zahl1).replace('.', ',')
            lsg = "{0:.2f}€".format(zahl2-zahl1).replace('.', ',')
        elif typ <=3:                                               #ganze Zahlen
            exp = random.randint(2,4)
            zahl1 = 10**exp
            zahl2 = random.randint(1,zahl1-1)
            text = "ergänze {} zu {}".format(zahl2, zahl1)
            proText = text
            lsg = str(zahl1 - zahl2)
        else:                                                       #Zahlen kleiner 0
            exp = random.randint(0, 2)
            zahl1 = 10**(-1*exp)
            zahl2 = random.randint(1,9)*zahl1/10
            text = "ergänze {0:.{1}} zu {2}".format(zahl2, exp, zahl1).replace('.', ',')
            proText = text
            lsg = "{0:.{1}}".format((zahl1 - zahl2),exp).replace('.', ',')
        return typ, text, proText, lsg,  zahl2-zahl1
... das funktioniert (fast - siehe unten)
__blackjack__ hat geschrieben: Dienstag 7. Juni 2022, 20:56 @Pitwheazle: Wenn man so gruselige Hacks mag…
Ich probiere gerne alternative Vorschläge aus. Mit dem obigen Code habe ich mich schon ziemlich abgemüht. Ich möchte aber Kommas in den Zahlen. Die Funktion "round" macht bei mir auch nicht was sie soll, round(1.20,2) schneidet die Null ab.
Und der Vorschlag von @sparrow mit localization ist mir auch noch nicht gelungen so umzusetzen, dass etwas in meinem Sinne passiert:
sparrow hat geschrieben: Dienstag 3. Mai 2022, 14:59 @Pitwheazle: Mein Bauchgfühl sagt mir, dass das hier zielführender für deinen Anwendungsfall ist.
Was noch nicht funktioniert:
Die Ergebnisse der Typen < 3 (Zahlen < 1) werden nicht akzeptiert:
Bild
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Runden ist auch nicht das richtige. Du musst formatieren, da kannst du die Anzahl der Stellen bestimmen.
Pitwheazle
User
Beiträge: 869
Registriert: Sonntag 19. September 2021, 09:40

__deets__ hat geschrieben: Mittwoch 8. Juni 2022, 08:40 Runden ist auch nicht das richtige. Du musst formatieren, da kannst du die Anzahl der Stellen bestimmen.
Sag ich doch - wenn ich das auch trotzdem nicht gut finde. Meinen Schüler habe ich immer versucht klarzumachen, dass die Antwort "1,2" für die Aufgabe "Runde 1,200 auf zwei Stellen nach dem Komma" falsch ist.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Pitwheazle: 1,200 mag ”falsch” sein, aber 1,2 € eben auch. Muss man halt je nach Situation passenden Code dafür schreiben. Aber eben mehr explizit, eine Funktion `format_number()` und eine `format_currency()` statt das mit `round()`, `format()`, und `replace()` überall ad hoc, über den kompletten Ausdruck verteilt, und mit potentiellen Nebenwirkungen für *alle* Punkte in einer Zeichenkette zu machen.

`NOTES` wäre tatsächlich ein Kandidat für eine Konstante, die definiert man dann aber nicht in einer Funktion oder Methode. Die ``while``-Schleife bei der Auswahl ist ein bisschen umständlich. Da dann sowieso eine Kopie der Teilliste erstellt wird, könnte man hier auch einfach eine neue Liste mit einer „list comprehension“ erstellen und da die Filterung als Bedingung einbauen.

Im Fall des 2€-Stücks fehlt ein Platzhalter in der Zeichenkette und bei Zahlen <0 fehlt ein "f" beim Format in der Vorlage.

Weiterer Fehler `loesung` basiert nicht immer auf ``zahl2 - zahl1`` was dann dem letzten Wert im Rückgabetupel widerspricht.

Diese Fehler sind IMHO ein guter Grund die Aufgabenerstellungen in Funktionen heraus zu ziehen, die man einzeln testen kann. Oder besser noch einen Datentyp dafür einführen, denn das Ergebnis besteht aus fast schon zu vielen Einzelteilen.

Zwischenstand (ungetestet):

Code: Alles auswählen

import random

DENOMINATIONEN = [2, 5, 10, 20, 50, 100]

...


def format_number(value, precision=2, trailing_zeros=False):
    text = f"{value:.{precision}f}".replace(".", ",")
    return text.rstrip(",0") if not trailing_zeros and "," in text else text


...
    ...
        ...
        
        aufgabentyp = random.randint(aufgabentyp_anfang, aufgabentyp_ende)
        #
        # Wechselgeld.
        #
        if aufgabentyp == 1:
            zahl1 = random.randint(5, 5950) / 100
            zahl2 = random.choice(
                [wert for wert in DENOMINATIONEN if wert > zahl1]
            )
            geld_art = "Schein" if zahl2 > 2 else "Stück"
            text = (
                f"Du hast für {format_number(zahl1, 2, True)}€ eingekauft und"
                f" bezahlst mit einem {format_number(zahl2)}€ {geld_art}."
                f" Wieviel Wechselgeld erhälst du?"
            )
            pro_text = (
                f"Wechselgeld: {format_number(zahl2)}€"
                f" - {format_number(zahl1, 2, True)}€"
            )
            loesung = zahl2 - zahl1
            loesungstext = f"{format_number(loesung, 2, True)}€"
        #
        # Ganze Zahlen.
        #
        elif aufgabentyp <= 3:
            zahl1 = 10 ** random.randint(2, 4)
            zahl2 = random.randint(1, zahl1 - 1)
            text = pro_text = f"ergänze {zahl2} zu {zahl1}"
            loesung = zahl2 - zahl1
            loesungstext = str(loesung)
        #
        # Zahlen kleiner 0
        #
        else:
            exponent = random.randint(0, 2)
            zahl1 = 10 ** (-1 * exponent)
            zahl2 = random.randint(1, 9) * zahl1 / 10
            text = pro_text = (
                f"ergänze {format_number(zahl2, exponent)} zu"
                f" {format_number(zahl1)}"
            )
            loesung = zahl2 - zahl1
            loesungstext = format_number(loesung, exponent)

        return aufgabentyp, text, pro_text, loesungstext, loesung
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@__blackjack__: die Fallen bei rstrip...

Code: Alles auswählen

format_number(100)
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sirius3: Meh, stimmt, müsste so aussehen:

Code: Alles auswählen

def format_number(value, precision=2, trailing_zeros=False):
    text = f"{value:.{precision}f}".replace(".", ",")
    return (
        text.rstrip("0").rstrip(",")
        if not trailing_zeros and "," in text
        else text
    )
Und natürlich wären Unittests eine tolle Sache. 😄
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Pitwheazle
User
Beiträge: 869
Registriert: Sonntag 19. September 2021, 09:40

Bärenstark, prima, Danke! Irgendwann lerne ich das hoffentlich auch!
__blackjack__ hat geschrieben: Mittwoch 8. Juni 2022, 10:20 Weiterer Fehler `loesung` basiert nicht immer auf ``zahl2 - zahl1``
Und damit ist dann das auch gelöst:
Pitwheazle hat geschrieben: Mittwoch 8. Juni 2022, 08:35 Was noch nicht funktioniert:
Die Ergebnisse der Typen < 3 (Zahlen < 1) werden nicht akzeptiert:
... jetzt müsste ich nur noch das mit der neuen Zeile hinbekommen.
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Was genau wird denn ausgegeben, wenn du <br> in die Zeichenkette einbaust?
Wenn das <br> zu lesen ist, musst du für den Abschnitt im Template möglicherweise das autoescape deaktivieren.
Pitwheazle
User
Beiträge: 869
Registriert: Sonntag 19. September 2021, 09:40

sparrow hat geschrieben: Mittwoch 8. Juni 2022, 18:49 Was genau wird denn ausgegeben, wenn du <br> in die Zeichenkette einbaust?
Der Code

Code: Alles auswählen

                f"Du hast für {format_number(zahl1,2)}€ eingekauft und"
                f" bezahlst mit einem {format_number(zahl2,0)}€ {art}."
                f"<br> Wieviel Wechselgeld erhälst du?")  
erzeugtBild
]
sparrow hat geschrieben: Mittwoch 8. Juni 2022, 18:49 Wenn das <br> zu lesen ist, musst du für den Abschnitt im Template möglicherweise das autoescape deaktivieren.
wie geht das?
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Das müsste es sein.
Pitwheazle
User
Beiträge: 869
Registriert: Sonntag 19. September 2021, 09:40

also

Code: Alles auswählen

{% autoescape on %}
<form action="{% url 'main' kategorie.slug %}" method="post">
    {% csrf_token %}
    <fieldset>
        {{ form.eingabe.label_tag }}
        {{ form.eingabe }}
        <input class="button-primary" type="submit" value="Prüfen">
    </fieldset>
</form>
{% endautoescape %}
ändert leider nichts. :?
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Ich bin etwas verwirrt, weil ich icht sehe, wo in dem Formular der Text stehen sollte, aber du musst das autoescape _aus_ nicht an schalten.
Pitwheazle
User
Beiträge: 869
Registriert: Sonntag 19. September 2021, 09:40

OK. Jetzt klappt es. Was ich jetzt wieder falsch gemacht habe, poste ich nicht - ist zu peinlich.
Antworten