Filtern in der Datenbank erledigen

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

Wenn wir schon über Pfusch reden, möchte ich einen großen Pfusch in meinem Code angehen.
Um was geht es (ich hoffe, ich bringe das verständlich rüber):
Mein Rechentrainer vergibt jetzt auch Noten (bisher fast nur schlechte). Die Kids müssen in jeder Woche eine bestimmte Anzahl Aufgaben machen und das in allen Kategorien die sie schon können müssten (zur Zeit sind das 25). Die Note wird bestimmt aus dem Prozentsatz wieviel der geforderten Aufgaben pro Kategorie erledigt wurden und von diesem werden dann noch Fehler abgezogen und auserdem auch noch die Klicks wenn Aufgaben weggeklickt werden und auch wenn die Kids die Lösung der Aufgabe anzeigen lassen. Da es sehr frustrierend ist, hier endlos Fehler anzusammeln, wird der Fehlerzähler nach einer festgelegten Anzahl von Aufgaben, die an einem Stück richtig gerechnet wurden, gelöscht. Da ist mir wieder nichts besseres eingefallen, als die Fehler und Abbrüche und Lösungen doppelt zu zählen. Zu jeder Kategorie gibt es für jeden Nutzer einen Eintrag in einer Datenbank "Zähler". Dort zähle ich die Fehler und lösche sie dann auch. Diese Fehler stehen aber auch in der Datenbank "Protokoll" und ihr habt mich schon mal hingewiesen, dass das Quatsch ist (ich konnte es aber mal wieder nicht besser). Den Pfusch möchte ich jetzt beseitigen (das funktioniert eh nicht über die verschiedenen Halbjahre).
Also das ist meine Idee:
Für jede Aufgabe wird ein Eintrag in "Protokoll" erzeugt. Dort wird auch jeweils gespeichert, ob die Antwort richtig oder falsch war und ob "Abbrechen" oder "Lösung" angeklickt wurde. Ich möchte jetzt in der Tabele "Zähler" anstelle der Fehlerzähler ein Feld mit einem Datum erzeugen und dort für die entsprechende Kategorie festhalten, zu welchem Zeitpunkt der Fehlerzähler gelöscht wurde und dann im Protokoll nur noch die Fehler addieren, die danach gemacht wurden.
Zunächst mal muss ich ein Feld für den Zeitpunkt definieren und diesem wollte ich als default zunächst mal den Beginn des Halbjahres übergeben. Wäre da

Code: Alles auswählen

fehler_ab = models.DateTimeField(default=datetime(2023, 8, 1, 0, 0, 0, 0))
korrekt?
Aber zur Ursprungsfrage: Wie bekomme ich die Summe der Fehler seit dem gespeicherten Datum? Soll ich da ein Filter benutzen? Irgendjemand hat hier mal gesagt, dass man diese Berechnung auch direkt in der Datenbank vornehmen kann.
Ich will euch auch hier nicht das neue Jahr verderben, indem ich den ganzen Code hier hochlade - hoffentlich reicht auch das:

Code: Alles auswählen

def uebersicht(req, schueler_id=0):
...
        protokoll = Protokoll.objects.filter(user=user, sj=user.sj, hj=user.hj)			    # alle Aufgaben des Users aus diesem Schulhalbjahr
..
        kategorien = Kategorie.objects.all().order_by('zeile')                                      # alle Aufgabenkategorien
...
        sj = user.sj
        hj = user.hj
...
        for kategorie in kategorien:
...
            protokoll_kategorie = protokoll.filter(kategorie = kategorie)
            if protokoll_kategorie.count() > 0:                                                     # es sind Aufgaben da
                zaehler_kategorie = Zaehler.objects.get(user=user, kategorie = kategorie)	    # die Kategorie wurde schon bearbeitet	
                kategorie_werte = (                                                                 # die Summen der einzelnen Kategoren des jeweiligen Users
                    protokoll_kategorie
                    .values("kategorie__zeile")
                    .annotate(richtig_sum=Sum('richtig'))
                    .annotate(zeit_sum=Sum(F('end') - F('start')))
                    )
                for k in kategorie_werte:
                    richtig_kat = k['richtig_sum']
                    zeit_kat = k['zeit_sum']
Da wäre es toll, wenn ihr mir erklären könntet, was die letzten neun Zeilen machen (die hat mir einer von euch erstellt).
und das ist dann der Code, mit dem ich zurzeit die diversen Fehler zähle und das möchte ich ändern:

Code: Alles auswählen

                    falsch_kat = zaehler_kategorie.fehler_zaehler
                    abbr_kat = zaehler_kategorie.abbr_zaehler
                    lsg_kat = zaehler_kategorie.lsg_zaehler
                    hilfe_kat = zaehler_kategorie.hilfe_zaehler
Wahrscheinlich wird jetzt noch das model "Protokoll" benötigt:

Code: Alles auswählen

class Protokoll(models.Model):
    user = models.ForeignKey(Profil, verbose_name='Benutzer', related_name='protokolle', 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:
    sj = models.SmallIntegerField(default=0)
    hj = models.SmallIntegerField(default=0)

    kategorie = models.ForeignKey(Kategorie, related_name='protokolle', on_delete=models.CASCADE)
...
    aufgnr = models.PositiveSmallIntegerField(default=0) 
    
    #der Aufgabentext:
    text = models.TextField(blank=True)

...
 
    #hier speichere ich die Lösung, wahlweise als zahl, u.U. auch (mehrere) Lösungen als String:
    wert = models.DecimalField('Wert', null=True, max_digits=20, decimal_places=7)
    loesung = models.JSONField()                                                    #hier können mehrere Werte eingegeben werden, der erste wird angezeigt wenn "Lösung anzeigen" angeklickt wird. Steht hier auch "indiv" so wird die Eingabe in der jeweiligen Funktion überprüft

...    
    #die Eingabe des users:
    eingabe = models.CharField(max_length=20, blank=True)

    versuche = models.PositiveSmallIntegerField('Versuche', default=0)
    #Eintrag richtig, falsch, Extrapunkte, Lösung anzeigen, Abbruch:
    wertung = models.CharField(max_length=10, blank=True)
    richtig = models.DecimalField(max_digits=3, decimal_places=1, default=0)

    falsch = models.PositiveSmallIntegerField(default=0)  
    abbr = models.BooleanField(default=True)
    lsg = models.BooleanField(default=False)    
    hilfe = models.BooleanField(default=False)  
    
    start = models.DateTimeField('Start', auto_now_add=True)
    end = models.DateTimeField('Ende', blank=True, null=True, default=None)
Schon im voraus vielen Dank für eure Geduld!
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Das Protokoll sollte dringend überarbeitet werden. Benutze keine kryptischen Abkürzungen, was ist ein sj oder ein hj? Und warum haben diese default-Werte? Die Angabe ist doch zwingend.
Was ist ein auf-GNR?
Den Aufgabentext zu speichern ist doch quatsch, zumal es ja viele Aufgaben gibt, die gar nicht in einen Text fassbar sind. Hier sollten nur die Parameter zur Aufgabe gespeichert werden, denn mit Hilfe der Aufgabenkategorie kann man ja dann die gesamte Aufgabe rekonstruieren. Es ist auch Unsinn zwischen Wert und Lösung zu unterscheiden.
Die Eingabe kann ja auch, soweit ich das verstanden habe, komplizierter sein als ein einfacher String.
Zu welchem Versuch wird denn die Eingabe gespeichert?
Wenn Du schon eine Wertung hast, in dem richtig oder falsch oder Lösung drinsteht, warum gibt es dann auch noch richtig, falsch abbr oder lsg als Felder? Wobei ich mal davon ausgehe, das lsg nicht Landessozialgericht heißt, sondern irgendwie sowas wie loesung_angezeigt.
Die vielen Punkte lassen befürchten, dass da noch viel mehr in der Tabelle steht?

Zum eigentlichen Problem: berechne die Note einfach aus den Daten, die Du eh im Protokoll stehen hast, eine eigene Tabelle mit Zählern ist unnötig.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Sirius3 hat geschrieben: Mittwoch 10. Januar 2024, 21:00 Das Protokoll sollte dringend überarbeitet werden. Benutze keine kryptischen Abkürzungen, was ist ein sj oder ein hj? Und warum haben diese default-Werte? Die Angabe ist doch zwingend.
OK, das hatten wir aber schon, ich finde hj und sj selbsterklärend, das mit dem default kann ich nicht mehr nachvollziehen, das kann ich aber, glaube ich, nachträglich nicht mehr ändern - oder?
Sirius3 hat geschrieben: Mittwoch 10. Januar 2024, 21:00 Was ist ein auf-GNR?
keine Ahnung - wo steht das? Gemeinsamer Nenner?
Sirius3 hat geschrieben: Mittwoch 10. Januar 2024, 21:00 Den Aufgabentext zu speichern ist doch quatsch, zumal es ja viele Aufgaben gibt, die gar nicht in einen Text fassbar sind. Hier sollten nur die Parameter zur Aufgabe gespeichert werden, denn mit Hilfe der Aufgabenkategorie kann man ja dann die gesamte Aufgabe rekonstruieren.
Das verstehe ich nicht, wie sollte das gehen? Ich habe hier mal eine Liste aus den Aufgaben zur Geometrie rauskopiert:
  • "Welche der Geraden sind senkrecht zueinander?"
    "Welche der Geraden sind parallel zueinander?"
    "Wie heißt diese Linie?"
    "Wie heißt dieses Viereck?"
    "Berechne den Umfang dieser Figur"
    "Berechne die Fläche dieser Figur"
    "Wie heißt dieser Körper?"
    "Ups, bei diesem Würfel sind ein paar Bausteine verlorengegegangen.<br>Wieviele sind es?"
    "Wie lauten die Koordinaten des Punktes A?"
    "Wieviele dieser {0} haben {1} Symetrieachse{2}?<br><br>{3}"
    "Wieviele dieser {0} sind punktsymetrisch?<br><br>{2}"
    "{0}Wieviele dieser Vierecke besitzen {1} Symetrieachse{2}?
    "{0}Wieviele dieser Vierecke sind punktsymetrisch?"
    "Das Dreieck ABC wird an der Spiegelachse S gespiegelt. <br>Wie lauten die Koordinaten des Punktes " + ecken[typ4] + "' des gespiegelten Dreiecks?"
... da gibt es aber auch noch umfangreichere Beispiele in anderen Kategorien.
Die Kids haben drei Chancen, die Frage zu beantworten und nach der Eingabe muss ich ja irgendwie den Text wieder an das Template schicken - wie soll das gehen, wenn ich ihn nicht speichere?
Sirius3 hat geschrieben: Mittwoch 10. Januar 2024, 21:00 Es ist auch Unsinn zwischen Wert und Lösung zu unterscheiden.
Nun ja, viele Aufgaben erfordern einfach nur eine Zahl als Antwort und die lässt sich einfach überprüfen, bei Termumformungen ist das aber nicht so einfach. So gibt es bei den Binomischen Formeln nicht nur eine richtige Antwort. Da kann ich auch nicht einfach versuchen, alle Möglichkeiten abzuspeichern, die muss ich nach der Eingabe analysieren .. und daher auch speichern.
Sirius3 hat geschrieben: Mittwoch 10. Januar 2024, 21:00 Die Eingabe kann ja auch, soweit ich das verstanden habe, komplizierter sein als ein einfacher String.
Eigentlich nicht. Oft eine Zahl, ansonsten ein String. Da ich das unterscheide, wird bei der einen Eingabe z.B. auch nur eine Zahl als Eingabe akkzeptiert. Ach so, ja, es gibt auch noch Wertetabellen, die mehrere Werte erfordern.
Sirius3 hat geschrieben: Mittwoch 10. Januar 2024, 21:00 Zu welchem Versuch wird denn die Eingabe gespeichert?
Siehe oben, oft muss ich den eingegebenen String analysieren. Ich gebe z.B. einen Hinweis zurück, wenn Groß- und Kleinschreibung nicht beachtet wurde, Koordinaten nicht in der geforderten Form eingegeben werden oder muss z.B. bei dem Zusammenfassen von Termen eine Möglichkeit finden unzählige richtige Antworten zu ermöglichen. Nach einer Umfrage im Internet sind meine Kollegen der Meinung, dass es keine eindeutige Lösung für das Vereinfachen eines Terms wie 4- 3ab-2a+3b²-2ab+5 gibt. Es gibt wohl keine Vorschrift dafür, wie Variablenbezeichnungen geordnet werden müssen. Belehre mich eines Besseren.
Sirius3 hat geschrieben: Mittwoch 10. Januar 2024, 21:00 Wenn Du schon eine Wertung hast, in dem richtig oder falsch oder Lösung drinsteht, warum gibt es dann auch noch richtig, falsch abbr oder lsg als Felder?
In Wertung könnte z.B. drinstehen "ffHr" da kann ich entnehmen, dass die Frage zunächst zweimal falsch und nach Anklicken der Hilfe richtig beantwortet wurde. Bei Wertetabellen ist das noch umfangreicher. Ich kann daraus entnehmen, wie die User an die Aufgabe rangehen und möglicherweise, wo ihr Problem liegt.
Sirius3 hat geschrieben: Mittwoch 10. Januar 2024, 21:00 Zum eigentlichen Problem: berechne die Note einfach aus den Daten, die Du eh im Protokoll stehen hast, eine eigene Tabelle mit Zählern ist unnötig.
In "zähler" steht halt auch noch drin, welcher Schwierigkeitsgrad für die nächsten 10 Aufgaben gewählt wurde (das ist einerseits vom Jahrgang, dem Lernfortschritt (der als "Stufe" gespeichert wird), der Wahl der Optionen (z.B. nur Zahlen ohne Komma - je nach Jahrgang und Schulform) abhängig).
Sirius3 hat geschrieben: Mittwoch 10. Januar 2024, 21:00 Zum eigentlichen Problem: berechne die Note einfach aus den Daten, die Du eh im Protokoll stehen hast, eine eigene Tabelle mit Zählern ist unnötig.
Na ja, das eigentliche Problem war, ob ich zu dieser Berechnung einen Filter verwenden soll oder die Auswertung in der Datenbank stattfinden kann.

... Vielleicht schaust du dir mal meine "rechentrainer.app" im Internet mal an. Möglicherweise sind die Aufgaben komplexer als du denkst. Es handelt sich nicht nur um die Grundrechenarten :).
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Mit jedem Satz, den Du geschrieben hast, bestätigst Du ja, das, was ich geschrieben hatte. Vieles ist nicht so einfach, wie Du das denkst, darstellen zu können und anderes ist einfach viel zu komplex dargestellt.
Was hilft Dir der Text "Berechne den Umfang dieser Figur", wenn Du die Koordinaten der Figur nicht mit ins Protokoll aufnimmst? Und der Text an sich ist überflüssig, weil der bei der Aufgabenkategorie eh immer gleich ist.

Ein üblicher Weg ist es, die Terme eines Polynomes nach Potenz und innerhalb einer Potenz die Variablen alphabetisch zu sortieren: 9 - 3a - 5ab + 3b², was dann die Koeffizienten c(n,i) = {9; -3, 0; 0, -5, 3} ergibt ∑_n ∑_i=0..n c(n,i) * a^i * b^(n-i)
Eine weitere Ordnung ist dann einfach eine weitere Zeile in diesem Zahlendreieck. Will man Polynome effizient auswerten, benutzt man das Horner-Schema, bei dem im Prinzip das Dreieck um 45° gedreht und von hohen zu niedrigen Potenzen abgearbeitet wird: (-5 * b - 3) * a + ((3*b + 0) * b) + 9
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Sirius3 hat geschrieben: Mittwoch 10. Januar 2024, 23:02 Was hilft Dir der Text "Berechne den Umfang dieser Figur", wenn Du die Koordinaten der Figur nicht mit ins Protokoll aufnimmst? Und der Text an sich ist überflüssig, weil der bei der Aufgabenkategorie eh immer gleich ist.
Natürlich sind die Koordinaten bzw. Werte der Figuren auch im Protokoll gespeichert. Und die Texte sind eben nicht in einer Kategorie gleich. Die Beispiele sind aus einer Kategorie, der Kategorie "geometrische Figuren", diese hat etliche Untergruppen - wie man sieht. Das ist eigentlich bei den meisten meiner Kategorien so.
OK, ich könnte die Texte in einer eigenen Datenbank speichern - mit den Hilfe Texten habe ich es auch so gemacht - dabei habe ich aber feststellen müssen, dass dadurch die Arbeit am Code viel umständlicher und vor allem unübersichtlicher wird.
Sirius3 hat geschrieben: Mittwoch 10. Januar 2024, 23:02 Ein üblicher Weg ist es, die Terme eines Polynomes nach Potenz und innerhalb einer Potenz die Variablen alphabetisch zu sortieren:
Das ist zwar üblich, andere Versionen können aber nach Meinung der Mathematiker im Internet nicht als falsch gewertet werden. Versuche eine Vorschrift zu finden, die diese Reihenfolge als richtig und andere als falsch bewertet. ... Vielleicht findest du die Diskussion, die ich dazu im Internet gestartet habe.

Nachtrag: Hier ist, wie ich das Problem gelöst habe: Ich überprüfe, ob die Eingabe der üblichen Schreibweise entspricht. Wenn der eingegebe Wert dem nicht entspricht, aber im Prinzip trotzdem richtig ist, gebe ich einen Hinweis und der User kann es ändern ohne dass die Eingabe als Fehler gewertet wird. Aber was machst du z.B. mit (c-b)(c+b) ? würdest du dann auf -b²+c² bestehen?

... diese Hinweise helfen mir bei meinem ursprünglichen Problem nicht wirklich weiter. Ich denke, ich werde das mit einem Filter lösen.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

OK, ich glaube, ich habe es kapiert. Die Zeilen:

Code: Alles auswählen

                kategorie_werte = (                                                                 # die Summen der einzelnen Kategoren des jeweiligen Users
                    protokoll_kategorie
                    .values("kategorie__zeile")
                    .annotate(richtig_sum=Sum('richtig'))
                    .annotate(zeit_sum=Sum(F('end') - F('start')))
                    )
sorgen dafür, dass die Werte (Summen) in der Datenbank berechnet werden. Also zunächst muss ich das (den) Query filtern und dann mit "annotate" in der Datenbank berechnen lassen.
Helft mir aber doch bitte noch mit der zweiten Frage oben im Text:

Code: Alles auswählen

fehler_ab = models.DateTimeField(default=datetime(2023, 8, 1, 0, 0, 0, 0))
das ist ja ein "naiv"es Datum, wie packe ich da unsere Zeitzone dazu, damit ich die nachher vergleichen kann? Und - ich habe das default ja schon in meine Datenbank eingetragen - kann ich das jetzt nachträglich ändern. Oder kann ich das Feld einfach löschen und neu anlegen?
Ach und nochwas. Das ist doch blöd:

Code: Alles auswählen

if abbr_kat == True:
    abbr_kat = 1
elif abbr_kat == False:
    abbr_kat = 0 
if lsg_kat == True:
    lsg_kat = 1
elif lsg_kat == False:
    lsg_kat = 0 
if hilfe_kat == True:
    hilfe_kat = 1
elif hilfe_kat == False:
    hilfe_kat = 0 
aber das geht nicht:

Code: Alles auswählen

for i in [abbr_kat, lsg_kat, hilfe_kat]: 
    if i == True:
        i = 1
    elif i == False:
        i = 0    
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

Pitwheazle hat geschrieben: Freitag 12. Januar 2024, 14:12 Das ist doch blöd:
Ja, das wirkt tatsächlich ziemlich blöd. Jede dieser Variablen wird von True/False zu 1/0. Warum? Und dann auch noch unter gleichem Namen. Das verwirrt doch sehr. Ich mag True/False sowieso lieber, als "magische" Zahlen, die auch mal 2 oder -1 werden könnten. Dazu muss man natürlich wissen, dass es diesen booleschen Datentypen gibt, und wie man damit umgehen kann. Vielleicht war das beim Excel Rechentrainer nicht drin? Obwohl man dort auch Zellen mit "=WAHR()" belegen kann, und dann einfacher direkt abfragen und unterscheiden kann ("=WENN(A1;mach dies;sonst das)"). Also kurz gesagt: Der ganze Ansatz hinkt irgendwo. Da würde ich mal 2-3 Schritte zurücktreten und den größeren Kontext betrachten, ob das nicht schlauer gelöst werden kann. Also nicht schlauer "True" in "1" umwandeln, sondern das gar nicht mehr nötig haben.
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.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Also das ist ganz einfach so, dass bei einer Aufgabe mittels eines boolschen Wertes gespeichert wird, ob die Antwort falsch war, die Aufgabe abgebrochen, die Hilfe aufgerufen oder die Lösung angezeigt wurde. Mittels

Code: Alles auswählen

                            .annotate(falsch_sum=Sum('falsch'))
                            .annotate(abbr_sum=Sum('abbr'))
                            .annotate(lsg_sum=Sum('lsg'))
                            .annotate(hilfe_sum=Sum('hilfe'))
werden diese Werte addiert. Das ergibt entweder eine Summe oder eben "True", wenn ein Wert, oder "False", wenn kein Wert gefunden wurde. Bei "richtig_kat" ist das etwas anderes, hier gibt es unter Umständen Extrapunkte (oder auch halbe) dies wird also nicht als boolscher Wert gespeichert. Inssgesamt ist das doch m.E. in Ordnung - ich fände es nicht so sinnvoll, diese falschen Eingaben (die nur Null oder Eins) ergäben als Ganzzahl zu speichern. Denke ich da falsch?
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Deine Namen sind nach wie vor so kaputt, dass man sie nur raten kann. Deshalb geht daraus auch nicht hervor, was sich dahinter verbirgt.
Wenn das boolsche Werte in der Datenbank sind, verstehe ich ehrlich gesagt nicht, warum du die summierst. Die zählt man doch eher.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Prima!

Code: Alles auswählen

                        .annotate(abbr_sum=Count('abbr'))
                        .annotate(lsg_sum=Count('lsg'))
                        .annotate(hilfe_sum=Count('hilfe'))
geht prima.
Könnt ihr mir bitte auch noch mit meinem Timecodeproblem helfen?
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

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

Pitwheazle hat geschrieben: Mittwoch 10. Januar 2024, 18:23 Zunächst mal muss ich ein Feld für den Zeitpunkt definieren und diesem wollte ich als default zunächst mal den Beginn des Halbjahres übergeben. Wäre da:

Code: Alles auswählen

fehler_ab = models.DateTimeField(default=datetime(2023, 8, 1, 0, 0, 0, 0))
korrekt?
und

Code: Alles auswählen

if zaehler_kategorie.fehler_ab < datetime(2024, 1, 1, 0, 0, 0, 0):
bringt den Fehler:

Code: Alles auswählen

can't compare offset-naive and offset-aware datetimes

Code: Alles auswählen

if zaehler_kategorie.fehler_ab.replace(tzinfo=None) < datetime(2024, 1, 1, 0, 0, 0, 0):
... hilft zwar, ich wüßte aber gerne wie ich

Code: Alles auswählen

fehler_ab = models.DateTimeField(default=datetime(2023, 8, 1, 0, 0, 0, 0))
richtig ergänzen muss.
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Ich verstehe dein Vorgehen ehrlich gesagt nicht. Also warum du Dinge doppelt zählst und dann irgendwelche Protokolle und Fehler löscht.
Wenn doch jeder Eintrag in diesem Protokoll einen Zeitstempel hat, dann selektiere doch einfach entsprechend aus der Datenbank, statt da einen Schattendatenhaltung zu machen? Auch DatetimeFields können entsprechend in einem Filter verwendet werden. Wenn du also nur die Fehler in einem bestimmten Zeitraum selektieren möchtest, dann selektiere nur die entsprechenden Einträge.

Also statt einer komplizierten Aufbewahrung an zweiter Stelle, einfach ein: Selektiere mir aus dem Protokoll alle Einträge des Schülters, im Zeitraum von x bis y und zähle dabei die aufgezählten Felder.
Das ist doch viel einfacher als irgendwelche Datenbankeinträge für Startpunkte zu machen und da dann irgendwelche Summe rein zu legen.

Django hat die util funktion make_aware um ein naives DateTime-Objekt mit einer entsprechende Timezone zu versehen.
Zuletzt geändert von sparrow am Freitag 12. Januar 2024, 23:27, insgesamt 1-mal geändert.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

sparrow hat geschrieben: Freitag 12. Januar 2024, 23:19 Ich verstehe dein Vorgehen ehrlich gesagt nicht. Also warum du Dinge doppelt zählst und dann irgendwelche Protokolle und Fehler löscht.
Wenn doch jeder Eintrag in diesem Protokoll einen Zeitstempel hat, dann selektiere doch einfach entsprechend aus der Datenbank, statt da einen Schattendatenhaltung zu machen?
... das ist doch genau der Inhalt meines Posts. Genau das will ich jetzt ändern und dafür will ich den Zeitstempel ergänzen, damit ich im nächsten Halbjahr das "richtig" machen kann und die doppelte Buchführung beenden kann:
Pitwheazle hat geschrieben: Mittwoch 10. Januar 2024, 18:23 Wenn wir schon über Pfusch reden, möchte ich einen großen Pfusch in meinem Code angehen.
... aber der default Zeitstempel braucht vorübergehend halt noch die Zeitzone ...
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Aber wofür brauchst du denn den Default Zeistempel?
Für was soll der denn Default sein, dass der sich nie ändert? Gibt es denn überhaupt die Möglichkeit, dass ein Datensatz _ohne_ diesen Zeitstempel angelegt wird? Wenn nein, dann ist das auch nicht sinnvoll einen Defaultwert anzulegen.

Ich würde ja sagen, da wird eher andersrum ein Schuh draus.
Eine Tabelle in der man so etwas wie Schuljahre oder Halbjahre (deren Abkürzung ich übrigens ganz schrecklich finde, weil sie an eine Jugendorganisation in dunkler Vergangenheit erinnert) mit Zeitspannen definiert und _daraus_ dann möglicherweie das Datum holt.

Also: deine Statistik für Schuljahr 2023/2024 und dann wird entsprechend des Datums selektiert.
Oder man macht es sich _im Code_ so einfach, dass das immer an einem bestimmten Datum im Jahr beginnt oder endet. Aber auch dann braucht mand as ja nicht in der Datenbank.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Ich muss die bestehenden 140000 Einträge irgendwie kenntlich machen. Am 1.2. werde ich den Zeitstempel mit dem entsprechenden Zeitsempel ersetzen und immer wenn der Fehlerzähler aktiviert wird, werde ich den Zeitstempel durch das aktuelle Datum ersetzen. Zur Not bekomme ich das ja mit ".replace(tzinfo=None)" ja hin, ich wollte es aber mal ausnahmsweise richtig machen :).
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Haben die bestehenedn 140_000 Datensätze denn einen Zeitstempel?
Wenn ja, dann nimm die einfach.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Eben nicht, darum geht es ja, den will ich jetzt nachtragen. Im Internet gibt es ja Beispiele (zB.. https://stackoverflow.com/questions/186 ... e-datetime) , die beziehen sich aber immer auf die USA. Ich dachte, ihr wisst auf Anhieb, wie man das auf MEZ umstellt.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

wenn ich das richtig verstehe brauchst du den Zeitstempel doch primär wegen des Datums und der muss mich sekundengenau sein, oder? Wenn ja dann bleib besser bei Django-Default UTC (Universell Time Code, entspricht im Prinzip der Greenwich Time). Also hast du 1 oder 2h Versatz zu MEZ bzw. MESZ.

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

Ja, das ist ja das Problem. Wenn ich den Zeitstempel setze, ab dem die fehler nicht mehr gezählt werden, muss das sekundengenau sein, die setzte ich dann mit = timezone.now() (hoffentlich stimmt das so). Für die Unterscheidung für die alten Protokolle, benutze ich das gleiche feld und ich hatte befürchtet, dass das bei der Abfrage Probleme gibt.
In meinen settings steht natürlich "TIME_ZONE = 'Europe/Berlin'". Ich habe jetzt noch nicht verstanden, ob ich mit "datetime.datetime(2023, 8, 1, 0,0,0,0, tzinfo=pytz.UTC)" das default auf UTZ setze (das wäre in diesem Fall ziemlich egal, da kommt es auf 1,2 Stunden nicht an), ich verstehe aber nicht, ob ich "UTZ" durch "MEZ" ersetzen kann, oder durch "UTC+1" bzw. "UTC+2" - und muss man da Sommerzeit und Winterzeit unterscheiden.
... ich probiere das jetzt einfach mal aus. (Ich könnte jetzt wieder jammern, dass ich in meinem StarBasi zur Not nachprüfen könnte, was da RAW gespeichert wird und bei Django nicht - aber die Diskussion hatten wir ja schon)
Antworten