Ist Django für mein Projekt geeignet?

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

sparrow hat geschrieben: Dienstag 8. Februar 2022, 17:21Läuft doch?
Ja, läuft, ich möchte aber die Geheimnisse ergründen, mit denen die Aufgaben erstellt werden, speziell, wie die Zufallszahlen eingebunden sind..
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Das funktioniert aber doch nur, wenn die Felder im modul "Aufgaben" mit den richtigen Inhalten gefüllt sind und wie die richtige Lösung erstellt wird, erschließt sich mir auch noch nicht - sorry dafür.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich habe das ganze auch nicht durchgeackert, aber in der Datenbank ist das hier:

Code: Alles auswählen

18:07 $ sqlite3 ~/Downloads/db_sqlite3
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite> .tables
auth_group                  core_question             
auth_group_permissions      core_result               
auth_permission             django_admin_log          
auth_user                   django_content_type       
auth_user_groups            django_migrations         
auth_user_user_permissions  django_session            
core_category             
sqlite> select * from core_question
   ...> ;
1|Du kaufst für {low:.2f} € ein und bezahlst mit einem {high:.2f} € Schein. Wie viel Wechselgeld (in Euro) erhälst du?||1
2|Ein Spiel kostet {low:.2f} Euro. Du hast {high:.2f} Euro. Wie viel Euro bleiben übrig, wenn du das Spiel gekauft hast?||1
sqlite> select * from core_category;
1|Ergänzen||
2|Addieren||
3|Subtrahieren||
So wie ich das sehe werden einfach zwei Zufallszahlen erzeugt, und das Ergebnis, immer die Differenz. Ohne weitere Parametrisierung. Weil die Kategorien Ergaenzen und Addieren das gleiche darstellen - es gibt eine niedrige und eine hohe Zahl, und die Differenz davon.

Eigentlich gehoert an die Kategorie die Information, welcher Code laufen muss, um dafuer eine Aufgabe zu generieren. Denke ich jedenfalls. Das its ja aber auch nur eine erste Skizze.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Wie hast du das gemacht?
Wenn ich den Browser benutze sehe ich nur die Struktur:
Bild
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

__deets__ hat geschrieben: Dienstag 8. Februar 2022, 15:18 Ich benutze dazu einfach sqlite3 auf der Kommandozeile.
Ich habe "sqlite3" im Terminal und in der Shell probiert - das war's aber wohl nicht?
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Und selbst mit dem sqlite-Browser kommst du an die Informationen. Du musst dir nicht die Datenbankstruktur sondern die Daten anschauen.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Danke, jetzt habe ich es gefunden!
Und - warum auch immer - jetzt sind sie auch im Projekt.
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

__deets__ hat geschrieben: Dienstag 8. Februar 2022, 18:18 Eigentlich gehoert an die Kategorie die Information, welcher Code laufen muss, um dafuer eine Aufgabe zu generieren. Denke ich jedenfalls. Das its ja aber auch nur eine erste Skizze.
Genau so würde ich es auch machen. Der Code war ja nur zum Zeigen, wie es im Web aussehen könnte. Damit das ganze dann nicht ohne Funktion ist, habe ich eine Rechnung (Differenz) hinterlegt. Man könnte sich jetzt z. B. ein Wörterbuch bauen, das Namen auf Funktionen abbildet und diesen Namen dann bei der Kategorie hinterlegen. Reicht für den Umfang des originalen Rechentrainers aber auch noch nicht. Das wird am Ende noch komplexer...

Viele Grüße
Whitie
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

__deets__ hat geschrieben: Dienstag 8. Februar 2022, 18:18 Eigentlich gehoert an die Kategorie die Information, welcher Code laufen muss, um dafuer eine Aufgabe zu generieren. Denke ich jedenfalls. Das its ja aber auch nur eine erste Skizze.
Das klingt interessant, da melde ich mich in ein paar Monaten wieder, wenn ich einige grundlegendere Dinge verstanden habe (falls das jemals geschieht).
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

BildDa bin ich schon wieder. Ihr habt mir so geduldig bei meinen Anfängerfragen geholfen, da wage ich mich an weitere Fragen:

Ich hatte ja ganz am Anfang geschrieben, dass meine Fragen nicht einfach in eine Datendank gepackt werden können, da ich viel über Code erstelle. Wie das aussieht, muss der ja in den views-Ordner. Der wird dann aber sehr lang. Kann man den in Unterordner unterteilen?

Ich habe mich auch schon an einer Datenbankstruktur versucht und bin da nicht so ganz sicher, ob ich auf dem richtigen Weg bin. Ich bin auch nicht so sicher mit den Benennungen. Ich nenne jetzt mal die einzelnen Klassen unter models Tabellen (in Whities Beispiel "category", "question" und "result") und alle zusammen ergeben die Datenbank - ist das richtig so?

Ich hätte dann folgende Tabellen:
1. Kategorien (ich nenne sie möglicherweise Module) davon gibt es entsprechend meinem bestehenden Rechentrainer 35 verschiedene (...Addition ... Bruchrechnung ... negative Zahlen ... Geometrie ... Funktionen ...usw)
2. Aufgaben (das würde ich aus Whities Beispiel übernehmen - für die Fragentexte)
3. Schulen
4. Lehrer
5. Gruppen (hier würde ich Gruppen von Schülern zusammenfassen auf die jeweils ein Lehrer zugreifen kann)
6. Schüler
und jetzt kommt das Schwierige:
7. Protokoll (das entspricht Whities "result". Hier speichere ich in z.Zt. 180 Zeilen die letzten 180 Aktionen jedes Schülers. Das sind halt für jeden Schüler 180 Zeilen. Packt man die für alle Schüler in eine gemeinsame Tabelle oder muss die in die Tabelle "Schüler". Wenn ja, wäre das ein Array mit 180 "Zeilen" und jede besteht bei mir z.Zt. aus etwa 11 "Spalten" zum Teil String, Integer, Dezimal ... wie definiert man das?
und ebenso die Daten:
Für jeden Schüler speichere ich die Daten von der 35 Kategorien (siehe oben) als "Zeilen" und jede hat zur Zeit 44 "Spalten", wie oben String, Integer, Dezimal. Dabei ist zu beachten, dass nicht alle Schüler die 35 Kategorien auch bearbeiten.
Das sieht z.Zt. so aus (blau unterlegt sind die Daten, die in die Tabelle "Schüler" kommen):
Bild
Am einfachsten wäre es ja, wenn in dem Moment, in dem sich ein Schüler anmeldet, eine eigene "Tabelle" jeweils für "Protokoll" und "Daten" angelegt würde. Geht Das?
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Du musst dich von diesem Tabellengedanken komplett lösen.
Die "Tabelle" in einer Datenbank haben nichts mit den Tabellen in einer Tabellenkalkulation zu tun. Außer den Namen im Deutschen.

Du hast hier verschiedene Modelle, die jeweils etwas repräsntieren.

Vielleicht wäre es einmal ganz gut den Ablauf des Programms zu skizzieren und dann daraus abzuleiten was es an views und Modellen geben muss.

Ja, die views.py lässt sich theoretisch in verschiedene Dateien aufteilen. Ich würde aber alle "views" - also die Endpunkte - darin behalten und die langen Funktionen für die Aufgaben - da müsste man dann im Detail schauen, wie generisch die sine, in ein oder mehrere entsprechende Module ausgliedern und von dort importieren.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Nun ja, aber irgendwie muss ich mir die Struktur ja vorstellen. Ich kenne, glaube ich, schon in etwa die Unterschiede.Aber da mein zukünftiger Web-Rechentrainer etwa meinem bestehenden Calc-Rechentrainer entsprechen soll, muss ich auch die Daten so ähnlich speichern. Dass die Namen der Kategorien/Module in Spalte A, z.B. nicht hier drin stehen, sondern in einer eigenen "Tabelle" ist mir schon klar - wie heißt denn jetzt der Teil der Datenbank, der in einer Klasse definiert ist? Einfach nur Klasse? Und, vor Allem, wie definiere ich eine deratige Klasse/Tabelle - als Array? Zur Zeit, habe ich die entsprechende Klasse/Tabelle so definiert:

Code: Alles auswählen

class Daten(models.Model):
    schueler = models.ForeignKey(Schueler, on_delete=models.CASCADE)
#    schueler=models.CharField(max_length=40)
    modul = models.ForeignKey(Module, on_delete=models.CASCADE)
#    zeile=models.PositiveSmallIntegerField(default=0)    #entspricht der Aufgabengruppe (1 bis 35)
    richtig=models.PositiveSmallIntegerField(default=0)
    zusatz=models.DecimalField(max_digits=5,decimal_places=2, default=0)
    falsch=models.PositiveSmallIntegerField(default=0)
    zeit=models.DurationField(default=0)
    abbrechen=models.PositiveSmallIntegerField(default=0)
    loesung=models.PositiveSmallIntegerField(default=0)
    hilfe=models.PositiveSmallIntegerField(default=0)

    datum_letzt=models.DateField(blank=True)              #wird nach 10 richtig gelösten Aufgaben eingetragen
    aufgof=models.PositiveSmallIntegerField(default=0)   #wie viele Aufgaben wurden am Stück richtig gelöst? löscht den Fehlerzähler nach LoeOF

    hj_richtig=models.IntegerField(default=0)            #Summe 1.Halbjahr
    hj_falsch: IntegerField=models.IntegerField(default=0)
    hj_Zeit=models.DurationField(default=0)
    
    gesamt_richtig=models.IntegerField(default=0)            #Summe gesamt
    gesamt_falsch: IntegerField=models.IntegerField(default=0)
    gesamt_Zeit=models.DurationField(default=0)

# im ersten Feld steht immer gestern, dann vorgestern ..., im letzten die Summe - das wird immer beim Öffnen aktualisiert wenn neuer Tag
    woche_richtig = ArrayField(models.DecimalField(max_digits=6, decimal_places=2, default=0),size=9)
    woche_falsch = ArrayField(models.DecimalField(max_digits=6, decimal_places=2, default=0),size=9)
    woche_zeit = ArrayField(models.DurationField(default=0),size=9)
... das wäre die Idee, dass in einer Klasse/Tabelle jeweils die Daten für ein Schüler und eine Kategorie/Modul gespeichert ist. Und da ist halt mein Problem, dass, wenn ich das so mache, alle Daten für alle Schüler in einer Klasse/Tabelle stehen - und das ist mir nicht geheuer - das Gleiche beim Protokoll - oder macht man das wirklich so? Dann würde also immer wenn ein Schüler ein neues Modul angeht eine neue Instanz der Klasse erzeugt.
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Das würde ich so tatsächlich nicht machen, denn viele der Dinge, die du hier speicherst, lassen sich "live" ermitteln.

Wenn du für jede Aufgabe, die ein Schüler abschließt, das "Ergebnis" speicherst, dann kannst du daraus ja jederzeit all das ermitteln, was du da oben in dem Model "Daten" darstellen willst. Deshalb brauchst du "Daten" nicht.

Ich mag es eher English, deshalb würde es vielleicht so etwas geben:

Code: Alles auswählen

class ExerciseResult(models.Model):
    student = models.ForeignKey(Student ....
    exercise = models.ForeignKey(Exercise ....
    created = models.TimeStamp(....
    duration = ....
    was_canceled = models.BooleanField(....
    was_right_answer = models.BooleanField(....
    ....
Wenn du das für jede gelöste Aufgabe speicherst, kannst du dir simpel heraussuchen, welche davon in welchem HJ wie gelöst wurden. Oder wie viele am Stück korrekt gelöst wurden. Etc.
Deshalb sage ich, du musst dich davon lösen, dass etwas auf Tabellenblärttern eingetragen wird. Stell es dir eher wie Karteikarten vor. Und du hast die Möglichkeit sehr schnell die Karteikarten zu zählen, sortieren, etc.
Es muss auch nichts beim Öffnen aktualisiert werden, wenn es geöffnet wird. Die Karten werden live ermittelt. Dann weiß man ja, was gestern war. Und was vorgestern.

Das Stichwort ist: Relationen in Datenbanken. Und - weil ich das immer für sehr hilfreich halte: Normalisierung.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

OK, das ist sehr hilfreich. Das heißt dann aber auch, dass jede Aufgabe, die irgendein Schüler (Schülerin) jemals gemacht hat in einer einzigen Klasse gespeichert wird - und das für alle Schülerinnen und Schüler die angemeldet sind - und ich daraus dann auch das Protokoll erstelle (halt nur, wenn es angefordert wird)? Da fällt es mir schwer, mir diese riesige Datenmenge auf einem Haufen (wie auch immer der heißt) vorzustellen.
Um das zu durchsuchen erstelle ich dann jeweils einen Index für Schüler, Modul und Datum (und möglicherweise noch Gruppe)? (lang lang ist es her, dass ich dBase3+ programmiert habe).
PS.: Ich finde es widerum lästig, immer alles englisch zu benennen. Ich versuche, mit der deutschen Benennung, die Teile, die ich selbst erstelle von denen zu unterscheiden, die zu Python oder Django gehören. Mir hilft es.
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Jeder Schüler ist eine Instanz dieser Klasse, das entspricht einer Zeile in der Datenbanktabelle. Ich habe zu hause eine Datenbank (Matrix Server) die ist aktuell 400GB groß und PostgreSQL hat null Probleme damit (i5, 4 Kerne, 32GB RAM). Es laufen auf dem selben Server auch noch weitere Datenbanken. Um den Index brauchst du dich in den meisten Fällen nicht selbst kümmern, Django legt automatisch welche an. Die Abfragen baut man dann schön mit dem ORM zusammen. Richtiges SQL braucht es meist nicht.
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Ich bin mir gerade nicht sicher, ob die Begriffe passen.

Unabhängig von Django:

Code: Alles auswählen

peter = Student("Peter", "Petersson")
An den Variablennamen "peter" wird eine Instanz der Klasse "Student" gebunden.

In Django:

Code: Alles auswählen

class Student(models.Model):
Es gibt eine Model "Student". Das ist eine Klasse, man spricht aber von einem Model. So eine Art Spezialfall, weil das eine Klasse ist, die dafür sorgt, dass das Model in der Datenbank abgebildet wird.

Es gibt also in meinem Bespiel weiter oben ein Model, das jedes Ergebnis, jedes Schülers abbildet.
Um die Datenmenge musst du dir erst einmal keine Gedanken machen. Dafür sind Datenbanken da.

Du brauchst erst einmal keinen Index zu erstellen. Das kann man machen, wen nman merkt, dass es sonst langsam ist.
nezzcarth
User
Beiträge: 1636
Registriert: Samstag 16. April 2011, 12:47

Code: Alles auswählen

… da ich viel über Code erstelle. Wie das aussieht, muss der ja in den views-Ordner.…
Da gibt es verschiedene Ansätze. Häufig wird dazu geraten, in den Views eher wenig zu machen und die Logik eher in den Modellen zu haben (sog. "fat models"). Andererseits müssen Views auch keine Funktionen sein, sondern können auch als Klassen geschrieben werden. Andere arbeiten mit einem Service Layer, der in einer service.py liegt. Interessant ist evtl., dass alles, was ein einzelnes Modul ist auch ein eigener Ordner sein kann, der eine __init__.py besitzt. Statt einer models.py kannst du also ein Package models haben, das mehrere einzelne Python-Dateien besitzt, sowie eine __init__.py. Für geteilte Funktionen, die an verschiedenen Stellen im Code verwendet werden kann man auch ein Modul 'commons' (oder so) mit reiner Bibliothskfunktion auf höchster anlegen. Da gibt es sehr viele Möglichkeiten. Wofür man sich entscheidet, hängt von den eigenen Erfahrungen aber auch den Vorlieben ab. Und vieles kann man nachträglich noch ändern. Vorteilhaft wäre nur, dass du vielleicht mit einer Versionsverwaltung arbeitest, wenn das nicht eh schon passiert (das ist leider noch mal etwas Zusätzliches, was man lernen muss, langfristig aber sehr hilfreich ist).

Persönlich wäre mein Vorschlag, vielleicht mit etwas Einfacherem ohne Bezug zu dem Rechentrainer einzusteigen. Das sind ja sehr viele Dinge, die da parallel gelernt werden müssen. Da macht es die ganze Komplexität des Rechentrainers vielleicht nicht gerade einfacher. Ich glaube auch, die Tatsache, dass schon eine Vorversion existiert, verleitet dazu, bestimmte Designentscheidungen übernehmen zu wollen, die man in Django sonst vielleicht anders treffen würde.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

nezzcarth hat geschrieben: Mittwoch 9. Februar 2022, 20:29 Persönlich wäre mein Vorschlag, vielleicht mit etwas Einfacherem ohne Bezug zu dem Rechentrainer einzusteigen. Das sind ja sehr viele Dinge, die da parallel gelernt werden müssen. Da macht es die ganze Komplexität des Rechentrainers vielleicht nicht gerade einfacher. Ich glaube auch, die Tatsache, dass schon eine Vorversion existiert, verleitet dazu, bestimmte Designentscheidungen übernehmen zu wollen, die man in Django sonst vielleicht anders treffen würde.
Nun, ich werde in diesem Jahr 69. Vor meiner Pensionierung schaffe ich das Projekt also nicht mehr. Jetzt muss ich nur aufpassen, dass ich es schaffe, bevor die Demenz schlimmer wird. Spaß beiseite. Ich versuche mich ja parallel an den kleinen Projekten, die in den Online-Tutorien beschrieben werden und habe schon ein Projekt für Blogs angefangen und eins um Bücher zu sortieren. Parallel versuche ich aber immer, das was ich gelernt habe in meinem Rechentrainer Projekt einzubauen. Jetzt muss ich in den Tutorien noch rausbekommen, wie man Benutzer einbindet.
Aber am Meisten habt ihr mir bis jetzt geholfen. Außer @ Whitie, dessen Struktur ich z.Z. versuche zu ergründen (nicht Whities sondern die seines Codes) und vor Allem auch @sparrow der mir sehr geholfen hat, mich jetzt von der bisherigen Datenstruktur des Rechentrainers zu lösen.
Das muss ich jetzt bald soweit hinbekommen, dass ich im Urlaub mit einem 12'' Bildschirm weiterarbeiten kann (Was gibt es Schöneres, als mit Blick aufs Meer Programmierungsaufgaben zu lösen?). Ach und dann habe ich ja auch außer diversen Bau, Bastel und Betreuungsprojekten noch einen angefangenen Physiktrainer hier rumliegen. Es gibt viel zu tun, der Weg ist zwar nach Konfuzius das Ziel, aber irgenwie muss es ja auch weitergehen!
nezzcarth hat geschrieben: Mittwoch 9. Februar 2022, 20:29
… da ich viel über Code erstelle. Wie das aussieht, muss der ja in den views-Ordner.…
Da gibt es verschiedene Ansätze. Häufig wird dazu geraten, in den Views eher wenig zu machen und die Logik eher in den Modellen zu haben (sog. "fat models"). Andererseits müssen Views auch keine Funktionen sein, sondern können auch als Klassen geschrieben werden. Andere arbeiten mit einem Service Layer, der in einer service.py liegt. Interessant ist evtl., dass alles, was ein einzelnes Modul ist auch ein eigener Ordner sein kann, der eine __init__.py besitzt. Statt einer models.py kannst du also ein Package models haben, das mehrere einzelne Python-Dateien besitzt, sowie eine __init__.py. Für geteilte Funktionen, die an verschiedenen Stellen im Code verwendet werden kann man auch ein Modul 'commons' (oder so) mit reiner Bibliothskfunktion auf höchster anlegen. Da gibt es sehr viele Möglichkeiten. Wofür man sich entscheidet, hängt von den eigenen Erfahrungen aber auch den Vorlieben ab. Und vieles kann man nachträglich noch ändern. Vorteilhaft wäre nur, dass du vielleicht mit einer Versionsverwaltung arbeitest, wenn das nicht eh schon passiert (das ist leider noch mal etwas Zusätzliches, was man lernen muss, langfristig aber sehr hilfreich ist).
??? Ich bin sowas von Anfänger (Meine eigene Erfahrung ist Null). Ich weiß nicht so recht, was ich hiermit machen soll. Kannst du mir das einfacher, mit einem Beispiel, erklären?
Versionsverwaltung hatte ich mal reingeschaut und mich bei Github angemeldet, wenn du meinst, kümmere ich mich nochmal drum.
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Ich glaube, die Dinge, die @nezzcarth eingeworfen hat, würden dich im Augenblick eher verwirren.
Django gibt ja eine gewisse Struktur vor. Du machst nichts verkehrt, wenn du dich erst einmal daran hälst.
Mitnehmen musst du nur, dass die Änderungen minimal sind, wenn du irgewann das Gefühl hast, dass zum Beispiel die views.py zu unübersichtlich wird. Aber das würde ich erst machen, wenn der Punkt erreicht ist.

Ich bin mir auch noch nicht so ganz sicher, ob die Funktionen in dem View tatsächlich so umfangreich werden. Wenn nämlich Exercises und deren Typen (im Sinne von verschiedene Arten von Aufgaben) selbst wieder Modelle sind, gehört die Logik vielleicht eher dort hinein.
Und vielleicht ist es auch sinnvoll das alles im Admin editierbar zu machen. Dann könnte man möglicherweise recht einfach neue Aufgabenarten hinzufügen und muss dafür nicht direkt im Code arbeiten.

Edit:
Ich unterstütze die Forderung nach einer Versionsverwaltung :)
Antworten