Ist Django für mein Projekt geeignet?
-
- User
- Beiträge: 1053
- Registriert: Sonntag 19. September 2021, 09:40
Sehe ich ein (hatte ich sogar mal bedacht)
Nun aufgabenstellung(modul_id) lieferte dir bisher einen Wert aus AUFGABEN, bei Nummer 3 also zum Beispiel subtrahieren.Pitwheazle hat geschrieben: Freitag 4. März 2022, 13:09 Das funktioniert nicht ("'str' object is not callable"). Wo ist mein Denkfehler?
Nota bene, es liefert nicht den String "subtrahieren", sondern die Funktion selbst: subtrahieren. Ohne Anführungszeichen.
Man kann nämlich subtrahieren() mit Klammern dahinter aufrufen, aber "subtrahieren"() kann man nicht aufrufen.

edit: Huch, da war ja noch eine Seite..!
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
-
- User
- Beiträge: 1053
- Registriert: Sonntag 19. September 2021, 09:40
So, bis hierhin klappt das - vielen Dank.
Jetzt habe ich aber schon wieder was Neues und komme nicht weiter:
Bei den meisten meiner 35 Aufgabentypen kommt, je nach Erfahrungsstufe, eine Abfrage nach den Schwierigkeitsstufen. Zum Beispiel können die Schülerinnen und Schüler bis zum 7ten Schuljahr noch entscheiden, ob sie mit oder ohne Kommazahlen üben wollen. Später z.B. bei den rechtwinkligen Dreiecken, ob nur Aufgaben zum Pythagoras, oder auch zu Höhen- und Kathetensätzen und später auch zur Trigonometrie aufgerufen werden sollen. In meinem bestehenden Rechentrainer werden im Normalfall immer 10 Aufgaben am Stück berechnet und die Abfrage kommt natürlich nur vor der ersten Aufgabe.
Ich habe versucht, eine neue Seite zu erstellen, in der diese Abfrage angezeigt wird, aber erstens klappt das mit dem Seitenaufruf nicht und zweitens weiß ich nicht so recht, wo ich das einbauen muss. Vermutlich muss ich für jede meiner 35 Aufgabentypen jeweils vor der Aufgabenstellung eine Startseite aufrufen.
Erschwerend kommt später noch hinzu, dass ich bisher, diese Einstellung nach den 10 Aufgaben auch noch mal genutzt habe, um eventuell, die "Stufe" anzupassen. Hat z.B. die Schülerinnen / der Schüler "mit Kommazahlen" angeklickt und dann auch noch 10 Aufgaben richtig, dann wird die Stufe raufgesetzt und die Abfrage kommt beim nächsten Aufruf nicht mehr.
Jetzt habe ich aber schon wieder was Neues und komme nicht weiter:
Bei den meisten meiner 35 Aufgabentypen kommt, je nach Erfahrungsstufe, eine Abfrage nach den Schwierigkeitsstufen. Zum Beispiel können die Schülerinnen und Schüler bis zum 7ten Schuljahr noch entscheiden, ob sie mit oder ohne Kommazahlen üben wollen. Später z.B. bei den rechtwinkligen Dreiecken, ob nur Aufgaben zum Pythagoras, oder auch zu Höhen- und Kathetensätzen und später auch zur Trigonometrie aufgerufen werden sollen. In meinem bestehenden Rechentrainer werden im Normalfall immer 10 Aufgaben am Stück berechnet und die Abfrage kommt natürlich nur vor der ersten Aufgabe.
Ich habe versucht, eine neue Seite zu erstellen, in der diese Abfrage angezeigt wird, aber erstens klappt das mit dem Seitenaufruf nicht und zweitens weiß ich nicht so recht, wo ich das einbauen muss. Vermutlich muss ich für jede meiner 35 Aufgabentypen jeweils vor der Aufgabenstellung eine Startseite aufrufen.
Erschwerend kommt später noch hinzu, dass ich bisher, diese Einstellung nach den 10 Aufgaben auch noch mal genutzt habe, um eventuell, die "Stufe" anzupassen. Hat z.B. die Schülerinnen / der Schüler "mit Kommazahlen" angeklickt und dann auch noch 10 Aufgaben richtig, dann wird die Stufe raufgesetzt und die Abfrage kommt beim nächsten Aufruf nicht mehr.
Kann man schon Aufgaben rechnen? Denn wirklich jede einzelne Verschnoerkelung zu programmieren, bevor nicht wenigstens der Ablauf fuer einen konkreten Fall mal durchgespielt wurde, ist im Zweifel Zeitverschwendung. Denn du loest hier gerade Detailprobleme, die auch gut noch im Nachhinein beantwortet werden koennen. Wohingegen es wahrscheinlich noch ganze Bereiche gibt, die zwingend sind, aber im Moment voellig unklar, wie die geloest werden. Und auch noch Rueckwirkung auf Modell und Seitenfluss haben koennen, der dann wieder bedeutet, dass Dinge angefasst werden muesen, wie eben solche Features.
-
- User
- Beiträge: 1053
- Registriert: Sonntag 19. September 2021, 09:40
Ja, man kann tatsächlich schon Aufgaben rechnen und ich bin jetzt dabei, meine Aufgabenstellungen aus meinem bestehenden Rechentrainer zu übertragen. Und das funktioniert auch schon zufriedenstellend und auch die Protokollseite funktioniert. (Soll ich das mal in Github freigeben?) Hier ist z.B. die Subtraktion:
Hier behelfe ich mich bei den unterschiedlichen Schwierigkeitsgraden, indem ich das Schuljahr übergebe. Wenn du meinst, mache ich auch erstmal so weiter.
Allerdings habe ich zwischenzeitlich was (hoffentlich) einfacheres versucht und wollte einen Aufgabenzähler einbauen. Wenn ich diesen in meinem View "Aufgaben" definiere ("aufgnr=0") und versuche hochzuzählen (aufgnr+=1) wird natürlich bei jedem Aufruf des Views der Zähler auf Null gesetzt, ich habe versucht eine globale Variable zu erstellen - leider ist mir das auch nicht gelungen.
Code: Alles auswählen
def subtrahieren(jg, stufe):
if jg==5:
zahl2=random.randint(1, 99)
result=random.randint(1, 49)
zahl1=result+zahl2
else:
rund1 = random.randint(0,2)
zahl2 = random.randint(1, 99)
zahl2=zahl2/10**rund1
rund2 = random.randint(0,2)
result = random.randint(1, 99)
result=result/10**rund2
zahl1=zahl2+result
zahl1=round(zahl1,(max(rund1, rund2)))
return zahl1, zahl2, result
Allerdings habe ich zwischenzeitlich was (hoffentlich) einfacheres versucht und wollte einen Aufgabenzähler einbauen. Wenn ich diesen in meinem View "Aufgaben" definiere ("aufgnr=0") und versuche hochzuzählen (aufgnr+=1) wird natürlich bei jedem Aufruf des Views der Zähler auf Null gesetzt, ich habe versucht eine globale Variable zu erstellen - leider ist mir das auch nicht gelungen.
Eine globale Variable waere ja auch eine Katastrophe. Wenn du zwei Benutzer gleichzeitig auf dem System hast, zaehlen die sich gegenseitig munter die Variable hoch. Wann immer du denkst, es muss ein global sein, denkst du falsch.
Mir ist nicht ganz klar, was dieser Zaehler soll, und wie der sich Verhaelt. Aber es gibt erstmal 3 Wege, den zu realisieren:
- wenn der zu dem User gehoert, der da gerade Aufgaben bearbeitet, und nur einmal vorhanden ist, dann kann man den in der Datenbank speichern. Vorteil: kann auch morgen/nach Absturz des Computer mit dem gleichen Wert genutzt werden.
- der gleiche User hat normalerweise eine Session via Cookie, und auch darin kann man einen solchen Zaehler verwalten. Das ist ggf. fluechtiger als die Datenbank, veraendert dafuer aber eben auch nicht die ganze Zeit ebendiese.
- der Zaehler wird von Seite zu Seite durchgereicht. Das heisst jede Seite muss den irgendwie mitbekommen, und wieder um eins hoeher ausliefern. Das ist aber ziemlich aufwaendeg.
Also wozu ist der gedacht?
Mir ist nicht ganz klar, was dieser Zaehler soll, und wie der sich Verhaelt. Aber es gibt erstmal 3 Wege, den zu realisieren:
- wenn der zu dem User gehoert, der da gerade Aufgaben bearbeitet, und nur einmal vorhanden ist, dann kann man den in der Datenbank speichern. Vorteil: kann auch morgen/nach Absturz des Computer mit dem gleichen Wert genutzt werden.
- der gleiche User hat normalerweise eine Session via Cookie, und auch darin kann man einen solchen Zaehler verwalten. Das ist ggf. fluechtiger als die Datenbank, veraendert dafuer aber eben auch nicht die ganze Zeit ebendiese.
- der Zaehler wird von Seite zu Seite durchgereicht. Das heisst jede Seite muss den irgendwie mitbekommen, und wieder um eins hoeher ausliefern. Das ist aber ziemlich aufwaendeg.
Also wozu ist der gedacht?
-
- User
- Beiträge: 1053
- Registriert: Sonntag 19. September 2021, 09:40
Ich hatte ja oben geschrieben, dass immer 10 Aufgaben am Stück gerechnet werden sollen. Anschließend würde wieder die Auswahlseite kommen. Einerseits ist das in meinem bestehenden Programm so gelöst und andererseits möchte ich dafür sorgen, dass nicht bei jeder unangenehmen Aufgabe das Thema gewechselt wird und die Kids sich durch diese 10 Aufgaben durcharbeiten. Wenn sie vorher abbrechen, gibt es bei mir sogar Minuspunkte.
Das das mit der globalen Variablen nicht so genial ist habe ich mir schon gedacht und eine Datenbanktabelle angelegt in der pro Schüler und Kategorie ein Zähler dafür definiert ist. Aber diese muss ich noch einbinden.
Das das mit der globalen Variablen nicht so genial ist habe ich mir schon gedacht und eine Datenbanktabelle angelegt in der pro Schüler und Kategorie ein Zähler dafür definiert ist. Aber diese muss ich noch einbinden.
Zunächst einmal würde ich Dir empfehlen, einfach mal ein paar Anfänge mit Django zu realisieren, zum Hineinkommen und als Übung. Dann bekommst Du hoffentlich schon ein Gefühl dafür, wie die Sache am Ende aussieht, und gewinnst dabei auch schon ein wenig Erfahrung mit Python, Django, HTML, CSS, webgerechten Grafiken und natürlich der Datenbank. Praktischerweise bringt Django dazu eigens einen Entwicklungswebserver mit (den Du aber bitte NIEMALS produktiv nutzen möchtest!).Pitwheazle hat geschrieben: Mittwoch 19. Januar 2022, 16:52 Ihr habt das sicher schon gewusst: Ich muss wohl den Teil von einem Server mieten und das ganze Projekt da hochladen. Jetzt wollen sie wissen, wieviele CPUs, RAMs und Festplatten ... ich brauche - keine Ahnung! Und da mein Rechentrainer kostenlos ist, möchte ich auch nicht so viel Geld ausgeben. Ihr scheint ja der Meinung zu sein, dass mein Projekt so zu realisieren ist - wie muss ich denn da jetzt weitermachen?
Der Punkt, den Du im Kern ansprichst, ist Performanceoptimierung. Wichtig ist aber, daß Du nicht jetzt schon quasi "ins Blaue" optimierst, sondern erst einmal etwas implementiert hast, das Du dann messen kannst. Auf Verdacht hin zu optimieren, ist immer eine vollkommen sinnlose Zeitverschwendung.Pitwheazle hat geschrieben: Mittwoch 19. Januar 2022, 16:52 Was ich mir auch noch nicht vorstellen kann ist, wie für 200 gleichzeitig angemeldete Schülerinnen und Schüler mein zukünftiges Pythonscript (das wird m.E. ziemlich groß) gleichzeitig Aufgaben generiert. Das liegt vielleicht daran, dass ich das mit der objektorientierten Programmierung noch nicht ganz verstanden habe.
Was genau ist Dir an der Objektorientierung denn noch unklar? Vielleicht kann dieses Forum da helfen, hier sind ein paar sehr kluge Köpfe versammelt.

Im Prinzip gilt zunächst das Prinzip der Datensparsamkeit, Du solltest also nicht mehr Daten erheben, als Deine Software am Ende benötigt. Rechtlich gesehen sind AGBs und bei kommerzieller Nutzung der Seite -- etwa weil dort Werbeanzeigen geschaltet werden oder der Zugang zur Seite kostenpflichtig ist -- ist auch ein Impressum vorgeschrieben -- ich würde aber auch bei nichtkommerziellen Seiten eines anbieten. Die Daten selbst sind in der Datenbank schon recht gut geschützt, wenn der Datenbankzugang entsprechend geschützt ist, das heißt: die Verbindung über TLS (früher: SSL) gesichert und mit Benutzername und Paßwort abgesichert ist, das mußt Du natürlich entsprechend konfigurieren. Es ist dabei zusätzlich sinnvoll, wenn die Datenbank so beschränkt wird, daß sie nicht von außen, sondern nur von Deiner Django-Website aus erreicht werden kann; Datenbankserver wie PostgreSQL bieten da entsprechende Konfigurationsmöglichkeiten, aber oft läuft der Datenbankserver auch auf demselben Server wie die Webseite, so daß der Datenbankserver dann nur auf das Lokale Device (IP-Adresse 127.0.0.1) lauscht. Oh, und noch ein Punkt: für den Fall, daß es doch mal ein Mistfink schafft, an Deine Datenbank zu kommen, sollten die Paßworte über eine Falltürfunktion verschlüsselt gespeichert werden, AFAIR macht das Django aber schon standardmäßig so.Pitwheazle hat geschrieben: Mittwoch 19. Januar 2022, 16:52 Ach, und dann noch der Datenschutz: Hier im Forum habe ich doch auch meinen Namen eingegeben und die AGBs abgeklickt. Und in Amazon und bei "Bettermarks" muss ich das ja auch. Und die Daten müssen dann mit einem Passwort geschützt werden ... wer kann mir sagen, was ich da jetzt genau beachten muss?
Wichtig ist auch, daß Du alles, was Du auf der Datenbank machtst, entweder mit Djangos OR-Mapper machst ODER bei manuellen Queries den Parametrierungsmechanismus des Datenbanktreibers benutzt. Diese beiden Komponenten kümmern sich nämlich um ein korrektes Quoting und schützen Dich vor SQL-Injections. Außerdem solltest Du jede Formulareingabe so penibel wie nur möglich überprüfen und Djangos CSRF-Middleware zum Schutz gegen entsprechende Angriffe nutzen. Obacht auch bei dem, was die Schüler eingeben und hochladen können; wenn ein Schüler eine Schadsoftware hochlädt (die können auch in Word- oder Excel-Dateien sein) und andere das so Hochgeladene von Deinem Server herunterladen können... you get the idea.
Wenn Du immer noch neugierig bist, ließe sich übrigens noch ein anderes Betriebsmodell für Deine Software nutzen, nämlich in einer Public Compute Cloud wie Heroku. Meine persönliche Empfehlung dazu wäre dann, Deine Webapplikation in ein Docker-Image zu packen -- der Nachteil ist zwar, daß Docker eine gründliche Einarbeitung braucht, aber die Vorteile sind vielfältig: Du kannst Deine Webapplikation dann unverändert laufen lassen, wo Du möchtest, egal ob auf Deinem Laptop mit MacOS oder Windows, auf einem kleinen Linux-Server in der Schule, in einer Public Compute Cloud oder ebendort sogar mit einem Orchestrator wie Kubernetes oder OpenStack.
Muß das denn in die Datenbank geschrieben werden? Ich glaube nicht...Pitwheazle hat geschrieben: Montag 24. Januar 2022, 16:53... geht das automatisch? Muss ich mich darum kümmern? Bei jedem Zugriff entstehen hier ja neue Einträge ... wo genau werden die gespeichert? Für jeden Nutzer werden ja nicht nur drei Werte (ZZ1, ZZ2 und Ergebnis) erzeugt, bei meiner jetzigen Version werden, abhängig von diesen Zufallszahlen auch z.B. individuelle Hilfetexte generiert - und die wiederum abhängig von der Kurszugehörigkeit der Nutzer (ich will hier nicht immer "Schülerinnen und Schüler" schreiben). Und weiterhin greife ich u.U. nach der Eingabe der Nutzer/in (!) nochmals auf die Anfangsdaten zu und interpretiere eine Falscheingabe.__deets__ hat geschrieben: Montag 24. Januar 2022, 16:10 Wenn die das gleichzeitig machen, dann werden die Ergebnisse eben in die Datenbank geschrieben.
[...]
Dass 30, 200 oder 1000 Nutzer gleichzeit nicht das Problem sind, ist mir ja schon klar. Nach meinem Denken geht es ja hier aber nicht um 5ms, sondern um die 20 Sekunden, die die Schülerinnen / der Schüler für die Antwort braucht. Wo liegt mein Denkfehler?
Fangen wir einfach mal mit dem "Denkfehler" an, dann wird es vielleicht klarer. Eine Webapplikation arbeitet eventbasiert; sie bekommt also eine Anfrage (Request), und dann generiert und sendet sie eine Antwort (Response). Sobald die Antwort versendet worden ist, ist das Skript zuende (das ist zwar nicht ganz richtig, aber für den Einstieg reichts.) Für Deine Webapp mit dem Anwendungsfall "Multiplikation" sieht das dann so aus:

Ich persönlich würde die Vermüllung der Datenbank komplett bleibenlassen und die Faktoren als versteckte Variablen in das HTML-Formular schreiben. Das alles ist ja nicht geheim und wird dem User ohnehin angezeigt -- und wenn man es geheim halten will, verschlüsselt man es mit einem nur dem Server bekannten Schlüssel und einem symmetrischen Verschlüsselungsalgorithmus wie AES. Und wenn der User dann seine Antwort eingegeben und das Formular abgeschickt hat, validiert der Server die Eingabedaten (ja, auch die aus den versteckten Feldern!), liest die Faktoren aus den versteckten Eingabefeldern und das Ergebnis aus dem "normalen" Eingabefeld, multipliziert die Faktoren und vergleicht das Resultat mit dem eingegebenen Ergebnis. Das wäre IMHO die einfachste Variante. Eine andere Möglichkeit bestünde darin, die Daten serverseitig in der Session zu speichern -- aber das böte sich IMHO eher bei der Akkumulation der Ergebnisse an.
Da dann nichts davon in der DB steht, braucht man dann auch kein großes Schema und kein Housekeeping für diesen Teil der Daten. Es sei denn, Du möchtest das Ganze am Ende statistisch auswerten, welcher Schüler bei welcher Berechnung besondere Probleme hat... aber das könnte man auch einfach ins Log schreiben und dann das auswerten, dazu braucht es kein relationales Datenbankmanagementsystem -- die werden zwar oft für Append-Only-Logs wie in Deinem Anwendungsfall benutzt, sind dafür aber nur begrenzt geeignet.

@Pitewheazle: der counter klingt schon wieder nach etwas, das du eigentlich in der Datenbank hast. Haben wir ja schon mal diskutiert. Die Datenbank beantwortet solche Fragen, ohne das man da irgendwelche counter führen muss.
-
- User
- Beiträge: 1053
- Registriert: Sonntag 19. September 2021, 09:40
@__deets__: Ich hatte schon befürchtet, dass du das schreibst:
... aber besser kann ich es noch nicht__deets__ hat geschrieben: Sonntag 6. März 2022, 07:30 @Pitewheazle: der counter klingt schon wieder nach etwas, das du eigentlich in der Datenbank hast. Haben wir ja schon mal diskutiert. Die Datenbank beantwortet solche Fragen, ohne das man da irgendwelche counter führen muss.
__deets__ hat geschrieben: Samstag 5. März 2022, 18:27 - wenn der zu dem User gehoert, der da gerade Aufgaben bearbeitet, und nur einmal vorhanden ist, dann kann man den in der Datenbank speichern. Vorteil: kann auch morgen/nach Absturz des Computer mit dem gleichen Wert genutzt werden.
Ich bezweifele, dass die Loesung einfacher ist, als die Pille "ich lerne es" zu schlucken. Denn der Counter kommt ja auch nicht von alleine. Wenn du zeigst, wie dein Datenmodell aussieht, und wo du das brauchst, kann man dir im Zweifel auch mit einer konkreten Abfrage, die sowas berechnet, helfen. Da musst du ja nicht alleine drauf kommen. Aber lieber helfen wir dir hier es richtig zu machen, als falsch. Und Hilfe ist ja in beiden Faellen von Noeten.
-
- User
- Beiträge: 1053
- Registriert: Sonntag 19. September 2021, 09:40
... nun ja, das mache ich ja.LukeNukem hat geschrieben: Samstag 5. März 2022, 22:02 Zunächst einmal würde ich Dir empfehlen, einfach mal ein paar Anfänge mit Django zu realisieren, zum Hineinkommen und als Übung. Dann bekommst Du hoffentlich schon ein Gefühl dafür, wie die Sache am Ende aussieht, und gewinnst dabei auch schon ein wenig Erfahrung mit Python, Django, HTML, CSS, webgerechten Grafiken und natürlich der Datenbank.
Das mit den Objecten wird ja schon besser. Mein Hauptproblem ist hier wahrscheinlich, dass ich noch zu "linear" denke. In meinem StarOffice Rechentrainer, werden die Aufgaben erstellt und angezeigt und das Programm bleibt stehen bis der Nutzer ein Ergebnis eintippt und anschließend kann ich bei der Bewertung der Eingabe immer noch auf alle Parameter der Aufgabenstellung zugreifen (nahezu alle Variablensind dort global definiert und können in allen Routinen genutzt werden. Mit diesem Prinzip ginge das natürlich nicht, wenn mehrere Nutzer gleichzeiti auf das Programm zugreifen. Da muss ich umdenken.LukeNukem hat geschrieben: Samstag 5. März 2022, 22:02Der Punkt, den Du im Kern ansprichst, ist Performanceoptimierung. Wichtig ist aber, daß Du nicht jetzt schon quasi "ins Blaue" optimierst, sondern erst einmal etwas implementiert hast, das Du dann messen kannst. Auf Verdacht hin zu optimieren, ist immer eine vollkommen sinnlose Zeitverschwendung.Pitwheazle hat geschrieben: Mittwoch 19. Januar 2022, 16:52 Was ich mir auch noch nicht vorstellen kann ist, wie für 200 gleichzeitig angemeldete Schülerinnen und Schüler mein zukünftiges Pythonscript (das wird m.E. ziemlich groß) gleichzeitig Aufgaben generiert. Das liegt vielleicht daran, dass ich das mit der objektorientierten Programmierung noch nicht ganz verstanden habe.
Was genau ist Dir an der Objektorientierung denn noch unklar? Vielleicht kann dieses Forum da helfen, hier sind ein paar sehr kluge Köpfe versammelt.![]()
Und ich frage euch klgen Köpfe doch schon Löcher in den Bauch (wenn mir auch manche Fragen peinlich sind).
... um den Rest kümmere ich mich, wenn ich mein Rechentrainer irgendwann mal veröffentlich ... und da werde ich sicher wieder die eine oder andere Frage dazu haben!
-
- User
- Beiträge: 1053
- Registriert: Sonntag 19. September 2021, 09:40
... da ist mir halt noch nicht klar, wie ich dann die Response überprüft wird. Dazu hätte ich die, zusammen mit der Aufgabenstellung erstellte, Lösung in meiner Protokolldatei gespeichert. Das wird nicht immer so einfach, da ich auch viele Aufgaben habe, bei denen nicht einfach eine Zahl die Lösung ist - wenn die Kids z.B. die Formel zur Berechnung von geometrischen Aufgabenstellungen angeben müssen. Ich hatte ja auch schon geschrieben, dass ich in meinem existierenden Programm teilweise, die falschen Antworten analysiere (da ich auf alle Parameter der Aufgabenstellung) zugreifen kann.LukeNukem hat geschrieben: Samstag 5. März 2022, 23:50 ...
Muß das denn in die Datenbank geschrieben werden? Ich glaube nicht...
Fangen wir einfach mal mit dem "Denkfehler" an, dann wird es vielleicht klarer. Eine Webapplikation arbeitet eventbasiert; sie bekommt also eine Anfrage (Request), und dann generiert und sendet sie eine Antwort (Response). Sobald die Antwort versendet worden ist, ist das Skript zuende (das ist zwar nicht ganz richtig, aber für den Einstieg reichts.)
... siehe obenLukeNukem hat geschrieben: Samstag 5. März 2022, 23:50 Ich persönlich würde die Vermüllung der Datenbank komplett bleibenlassen und die Faktoren als versteckte Variablen in das HTML-Formular schreiben. Das alles ist ja nicht geheim und wird dem User ohnehin angezeigt -- und wenn man es geheim halten will, verschlüsselt man es mit einem nur dem Server bekannten Schlüssel und einem symmetrischen Verschlüsselungsalgorithmus wie AES. Und wenn der User dann seine Antwort eingegeben und das Formular abgeschickt hat, validiert der Server die Eingabedaten (ja, auch die aus den versteckten Feldern!), liest die Faktoren aus den versteckten Eingabefeldern und das Ergebnis aus dem "normalen" Eingabefeld, multipliziert die Faktoren und vergleicht das Resultat mit dem eingegebenen Ergebnis. Das wäre IMHO die einfachste Variante. Eine andere Möglichkeit bestünde darin, die Daten serverseitig in der Session zu speichern -- aber das böte sich IMHO eher bei der Akkumulation der Ergebnisse an.
Ich hatte schon gehofft, dass ich das mit der Auswertung irgendwann auch hinbekomme. Ich hatte auch weiter oben geschrieben, dass ich irgendwann auch ermöglichen möchte, dass Lehrer sich anmelden können und die Ergebnisse für ihre Lerngruppen übersichtlich darstellen können - das ist ein großer Vorteil meines OpenOffice Rechentrainers. Das sieht dann etwa so aus:LukeNukem hat geschrieben: Samstag 5. März 2022, 23:50 Da dann nichts davon in der DB steht, braucht man dann auch kein großes Schema und kein Housekeeping für diesen Teil der Daten. Es sei denn, Du möchtest das Ganze am Ende statistisch auswerten, welcher Schüler bei welcher Berechnung besondere Probleme hat... aber das könnte man auch einfach ins Log schreiben und dann das auswerten, dazu braucht es kein relationales Datenbankmanagementsystem -- die werden zwar oft für Append-Only-Logs wie in Deinem Anwendungsfall benutzt, sind dafür aber nur begrenzt geeignet.![]()

Hier kann man mithilfe farblicher Kennzeichnung mit einem Blick die Probleme einzelner Schülerinnen und Schüler sowie der ganzen Lerngruppe erkennen.
-
- User
- Beiträge: 1053
- Registriert: Sonntag 19. September 2021, 09:40
Also denn, du hast es ja so gewollt (es ist mir schon unangenehm, bei jedem Problem hier nachzufragen und versuche halt erstmal, mir selbst was einfallen zu lassen und mit try and error zu lösen), also zeige ich mal wie ich mir das bisher vorgestellt habe. Zunächst möchte ich zeigen, wie das am Ende aussehen soll. Jeder Nutzer soll eine Startseite haben, die etwa so aussehen soll:__deets__ hat geschrieben: Sonntag 6. März 2022, 15:06 Ich bezweifele, dass die Loesung einfacher ist, als die Pille "ich lerne es" zu schlucken. Denn der Counter kommt ja auch nicht von alleine. Wenn du zeigst, wie dein Datenmodell aussieht, und wo du das brauchst, kann man dir im Zweifel auch mit einer konkreten Abfrage, die sowas berechnet, helfen. Da musst du ja nicht alleine drauf kommen. Aber lieber helfen wir dir hier es richtig zu machen, als falsch. Und Hilfe ist ja in beiden Faellen von Noeten.

und dann soll er/sie oder auch ich sehen können, was genau gemacht wurde:

Folgende Datenbanktabellen habe ich bisher angelegt:

In "Protokoll" werden die gestellten Aufgaben gespeichert:
Code: Alles auswählen
class Protokoll(models.Model):
user = models.ForeignKey(Schueler, verbose_name='Benutzer', related_name='protokoll', on_delete=models.CASCADE)
#gewertet werden nur die Aufgaben des jeweiligen Schuljabjahres, im Januar, Juni und August, kann der user aber auch schon festlegen, dass die Aufgaben für das nächste Schulhalbjahr gelten:
halbjahr = models.PositiveSmallIntegerField(default=0)
kategorie = models.ForeignKey(Kategorie, verbose_name='Kategorie', related_name='protokoll', on_delete=models.CASCADE)
typ = models.CharField(max_length=5, blank=True )
#der Aufgabentext:
text = models.TextField(blank=True)
#hier speichere ich die Lösung, wahlweise als zahl, u.U. auch (mehrere) Lösungen als String:
value = models.DecimalField('Wert', max_digits=20, decimal_places=7)
loesung = models.CharField(max_length=20, blank=True, verbose_name="Lösung")
#die Eingabe des users:
eingabe = models.CharField(max_length=20, blank=True, verbose_name="Eingabe")
falsch_eingabe = models.TextField(blank=True, verbose_name="Falscheingabe")
tries = models.PositiveSmallIntegerField('Versuche', default=0)
#Eintrag richtig, falsch, Extrapunkte, Lösung anzeigen, Abbruch:
wertung = models.CharField(max_length=5, blank=True, verbose_name="Wertung")
hilfe = models.PositiveSmallIntegerField(default=0)
start = models.DateTimeField('Start', auto_now_add=True)
bearbeitungszeit=models.FloatField(default=0)
- Im Februar, im Juni und Juli sind die Zeugnisnoten schon fertig und daher können bisher die Kids wählen, ob das neue Halbjahr angefangen werden soll, dann werden alle bisherigen Aufgaben in der Anzeig gelöscht und ein neues Schuljahr fängt an. Es gibt aber auch Schülerinnen und Schüler die auch im Februar oder Juni noch weiterarbeiten um im letzten Moment vielleicht doch noch ihre Zeugnisnote verbessern wollen - dafür ist das Feld "halbjahr", danach kann ich filtern
- Dann habe ich schon von der Option berichtet, dass, wenn die Kids Fehler in einer Kategorie gemacht haben, diese gelöscht werden, wenn sie eine bestimmte Anzahl Aufgaben richtig gelöst haben, ohne Fehler, Lösung anzeigen oder Aufgaben abzubrechen. Danach kann man sicher auch irgendwie filtern, das geht aber doch einfacher. Ich zähle pro Kategorie und Schüler die Fehler, Anzahl von Lösung anzeigen und Hilfe anklicken und dann auch die Anzahl der Aufgaben, die fehlerfrei am Stück gerechnet wurden und lösche dann entsprechenden die Zähler
- Dann wäre noch das Problem mit den Stufen: Nochmal das Beispiel: Der User wählt "Bruchrechnung auch mit Division" und schafft dann auch 10 Aufgaben dazu - dann steigt er 2 Stufen hoch und muss zukünftig Bruchrechnungsaufgaben auch mit Multiplikation und Division rechnen ("stufe_next" (welche Stufe könnte erreicht werden?), "stufe_zaehl" (Aufgaben ohne Fehler)).
- Dann will ich, dass immer 10 Aufgaben am Stück gerechnet werden, bevor die Auswahl wiederkommt ("aufgnr").
- Und Last but not Least: Wenn ich je user und Kategorie schon diese ganzen Daten zähle, kann ich auch noch die richtigen Antworten gleich mitzählen und dann hoffentlich benutzen, um eine Seite gestalten zu können auf der der user eine Anzeige bekommt, die der oben gezeigten entspricht - mit farblichen Markierungen in einer Tabelle (da habe ich noch keinerlei Idee, wie das geht)
Jetzt musst du ganz stark sein. Ich habe jetzt trotz deines Verbots doch nochmal diese Tabelle erstellt:
Code: Alles auswählen
class Zaehler(models.Model):
user = models.ForeignKey(Schueler, verbose_name='Benutzer', related_name='zaehler', on_delete=models.CASCADE)
kategorie = models.ForeignKey(Kategorie, on_delete=models.CASCADE, related_name="zaehler")
aufgnr = models.PositiveSmallIntegerField(default=0)
richtig = models.PositiveSmallIntegerField(default=0)
Extrapunkte = models.DecimalField(max_digits=5, decimal_places=2, default=0)
falsch = models.PositiveSmallIntegerField(default=0)
loesung = models.PositiveSmallIntegerField(default=0)
abbrechen = models.PositiveSmallIntegerField(default=0)
hilfe = models.PositiveSmallIntegerField(default=0)
stufe_next = models.PositiveSmallIntegerField(default=0) #wenn größer null dann wird nach 10 richtigen Eingaben die Stufe entsprechend hochgesetzt
stufe_zaehl = models.PositiveSmallIntegerField(default=0) #und hier wird gezählt
Wenn du mehrere Loesungen haben willst, dann speichert man das auch nicht als String! Du hast doch immer Zahlen als loesungen, oder nicht? Dann muessen das auch immer Zahlen sein. Wenn du also tatsaechlich speichern willst, das es mehrere Versuche gab, dann muss das eine 1:n-Beziehung von "Antwort" zu Protokoll sein. Warum heisst das nicht Aufgabe? Ich nenne das mal im folgenden so.
Womit auch schon sofort die "tries" wegfaellt, das ist dann einfach die Anzahl dieser Antworten. Die Frage, ob die Aufgabe schon richtig (oder falsch, wie du es formulierst) beantwortet wurde, ist dann die Kardinalitaet der Abfrage aller Antworten fuer die Aufgabe, bei denen der Wert dann gleich der Loesung ist. Wenn die gleich 1 ist (theoretisch natuerlich auch groesser, ab das sollte natuerlich nicht gehen), dann ist die Aufgabe richtig beantwortet.
Was mir jetzt fuer die ganze Logik von "10 Aufgaben muessen geloest werden" etc. pp fehlt ist, was denn da eigentlich fuer ein uebergeordnetes Ding zu gehort. Sowas wie ein Aufgabensatz.
Dann das halbjahr: das kann ja auch trivial berechnet werden, wenn die Aufgabe zum Zeitpunkt der Loesung eben noch im alten oder schon im neuen Halbjahr ist. Und dann ist die Frage: was ist denn mit Aufgaben, die man *anfaengt* im Halbjahr, aber dann jenseits des Zeugnis-Zeitpunkts erst die richtige Antwort gibt?
Und Bearbeitungszeit ist natuerlich einfach nur der Zeitpunkt der Erstellung der Aufgabe, oder ggf. der Erstellung eines uebergeordneten Aufgabensatzes, und des Zeitpunkt der richtigen Antwort.
Womit auch schon sofort die "tries" wegfaellt, das ist dann einfach die Anzahl dieser Antworten. Die Frage, ob die Aufgabe schon richtig (oder falsch, wie du es formulierst) beantwortet wurde, ist dann die Kardinalitaet der Abfrage aller Antworten fuer die Aufgabe, bei denen der Wert dann gleich der Loesung ist. Wenn die gleich 1 ist (theoretisch natuerlich auch groesser, ab das sollte natuerlich nicht gehen), dann ist die Aufgabe richtig beantwortet.
Was mir jetzt fuer die ganze Logik von "10 Aufgaben muessen geloest werden" etc. pp fehlt ist, was denn da eigentlich fuer ein uebergeordnetes Ding zu gehort. Sowas wie ein Aufgabensatz.
Dann das halbjahr: das kann ja auch trivial berechnet werden, wenn die Aufgabe zum Zeitpunkt der Loesung eben noch im alten oder schon im neuen Halbjahr ist. Und dann ist die Frage: was ist denn mit Aufgaben, die man *anfaengt* im Halbjahr, aber dann jenseits des Zeugnis-Zeitpunkts erst die richtige Antwort gibt?
Und Bearbeitungszeit ist natuerlich einfach nur der Zeitpunkt der Erstellung der Aufgabe, oder ggf. der Erstellung eines uebergeordneten Aufgabensatzes, und des Zeitpunkt der richtigen Antwort.
-
- User
- Beiträge: 1053
- Registriert: Sonntag 19. September 2021, 09:40
Nein, das sind nicht immer Zahlen. Die Kids müssen zum Beispiel auch Formeln zur Berechnung von Geometrieaufgaben eingeben oder Terme wie "3a+2b-5+b" berechnen - und da gibt es leider oft mehrere Lösungsmöglichkeiten. Die stehen dann unter "loesung".__deets__ hat geschrieben: Sonntag 6. März 2022, 16:53 Wenn du mehrere Loesungen haben willst, dann speichert man das auch nicht als String! Du hast doch immer Zahlen als loesungen, oder nicht? Dann muessen das auch immer Zahlen sein. Wenn du also tatsaechlich speichern willst, das es mehrere Versuche gab, dann muss das eine 1:n-Beziehung von "Antwort" zu Protokoll sein. Warum heisst das nicht Aufgabe? Ich nenne das mal im folgenden so.
Das mit den Abfrage über "tries" war mir schon klar. Ich hatte ja auch geschrieben, wenn ich die ganzen anderen Werte zähle, dann kommt es auf die Zahl der richtigen Lösungen auch nicht mehr an. Außerdem wollte ich auch u.U. sehen, welche Falscheingaben gemacht wurden - das fand ich als Lehrer immer sehr wichtig zu wissen, was falsch gemacht wurde. Daher habe ich überlegt, ob auch die Falscheingaben jeweils eine Protokollzeile bekommen.__deets__ hat geschrieben: Sonntag 6. März 2022, 16:53 Womit auch schon sofort die "tries" wegfaellt, das ist dann einfach die Anzahl dieser Antworten. Die Frage, ob die Aufgabe schon richtig (oder falsch, wie du es formulierst) beantwortet wurde, ist dann die Kardinalitaet der Abfrage aller Antworten fuer die Aufgabe, bei denen der Wert dann gleich der Loesung ist. Wenn die gleich 1 ist (theoretisch natuerlich auch groesser, ab das sollte natuerlich nicht gehen), dann ist die Aufgabe richtig beantwortet.
Der User wählt eine Kategorie aus und der Aufgabensatz besteht aus den 10 Aufgaben, die dazu jeweils jeweils erstellt werden. Nach 10 richtigen Eingaben kann wieder eine neue Kategorie gewählt werden - oder die Bearbeitung wird abgebrochen - das kostet aber Minuspunkte.__deets__ hat geschrieben: Sonntag 6. März 2022, 16:53 Was mir jetzt fuer die ganze Logik von "10 Aufgaben muessen geloest werden" etc. pp fehlt ist, was denn da eigentlich fuer ein uebergeordnetes Ding zu gehort. Sowas wie ein Aufgabensatz.
Anscheinend habe ich das noch nicht gut genug geklärt. Also: Wenn ich Zeugnisnoten mache, schaue ich mir an, was die Kids im Rechentrainer so gemacht haben. Wenn jemand zwischen zwei Noten steht, dann gebe ich ihm die Möglichkeit, sich nochmal in den Rechentrainer reinzuknien. Die anderen möchten aber gerne im z.B. im Juni weiterrechnen, obwohl sie keine bessere Note mehr bekommen können. Die klicken in dem, im Januar, Juni bzw. Juli aufpopenden Fenster auf "neues Schuljahr anfangen" und dadurch werden ihre bisher gerechneten Aufgaben g"gelöscht" (nicht mehr angezeigt) in der Datenbank wird das neue Schuljahr eingetragen (Im Juni 22 also "22-23-2" für das zweite Halbjahr) und damit werden alle ab dann gemachte Aufgaben im zweiten Halbjahr angezeigt. Bei dem zuerstgenannten Schüler, der noch für das Halbjahreszeugnis arbeitet, werden seine Aufgaben spätestens gelöscht wenn er seinen Rechentrainer im August öffnet.__deets__ hat geschrieben: Sonntag 6. März 2022, 16:53 Dann das halbjahr: das kann ja auch trivial berechnet werden, wenn die Aufgabe zum Zeitpunkt der Loesung eben noch im alten oder schon im neuen Halbjahr ist. Und dann ist die Frage: was ist denn mit Aufgaben, die man *anfaengt* im Halbjahr, aber dann jenseits des Zeugnis-Zeitpunkts erst die richtige Antwort gibt?
Sorry, das verstehe ich nicht. In "bearbeitungszeit" trage ich zur Zeit den Zeitraum ein, der zwischen Erstellung der Aufgabe und Eingabe der Lösung vergangen ist. Der Zeitpunkt der Erstellung der Aufgabe steht in "start".__deets__ hat geschrieben: Sonntag 6. März 2022, 16:53 Und Bearbeitungszeit ist natuerlich einfach nur der Zeitpunkt der Erstellung der Aufgabe, oder ggf. der Erstellung eines uebergeordneten Aufgabensatzes, und des Zeitpunkt der richtigen Antwort.
-
- User
- Beiträge: 1053
- Registriert: Sonntag 19. September 2021, 09:40
Ich finde den Fehler nicht:
Ein Ausschnitt meiner Protokollseite:

der zugehörige Ausschnitt aus dem HTML Template:

die ID 67 wird angezeigt (rechts) und, so dachte ich, auch weitergegeben (links)
hier der/die/das(?) URL Pattern:

und dann wollte ich mit Klick auf die Zeile mit der ID 67 ebendiese im Detail darstellen - es kommt aber nicht die mit 67, sondern die Details der Zeile mit der ID 204.

(Klar, wenn ich die Zeile mit der ID 204 anklicke bekomme ich eine Fehlermeldung ("out of range").
Ich weiß, ich stelle mich sicher wieder dusselig an, vielleicht suche ich auch an der falschen Stelle. Was stimmt nicht?
Ein Ausschnitt meiner Protokollseite:

der zugehörige Ausschnitt aus dem HTML Template:

die ID 67 wird angezeigt (rechts) und, so dachte ich, auch weitergegeben (links)
hier der/die/das(?) URL Pattern:

und dann wollte ich mit Klick auf die Zeile mit der ID 67 ebendiese im Detail darstellen - es kommt aber nicht die mit 67, sondern die Details der Zeile mit der ID 204.

(Klar, wenn ich die Zeile mit der ID 204 anklicke bekomme ich eine Fehlermeldung ("out of range").
Ich weiß, ich stelle mich sicher wieder dusselig an, vielleicht suche ich auch an der falschen Stelle. Was stimmt nicht?