Reihenfolge im Admintool

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

Auftragsgemäß habe ich jetzt mal angefangen, die ganzen Fragetexte aus dem Protokoll in eine eigene Datenbank zu übertragen, damit nicht in jedem Protokolleintrag auch der komplette Fragetext drinsteht. Also habe ich eine Datenbank mit den Fragen erstellt:

Code: Alles auswählen

class Frage(models.Model):
    kategorie = models.ForeignKey(Kategorie, related_name='fragen', on_delete=models.CASCADE)    
    typ = models.SmallIntegerField(default=0) 
    typ2 = models.SmallIntegerField(default=0) 

    titel = models.CharField(max_length=20, blank=True)
    text = models.TextField(blank=True)
    pro_text = models.CharField(max_length=100, blank=True)
    anmerkung = models.CharField(max_length=100, blank=True)

    def __str__(self):
        return f"{self.kategorie}, Typ: {self.typ} Typ2: {self.typ2}, {self.titel}, {self.text}"

    class Meta:
        unique_together = ['kategorie', 'typ', 'typ2']
        verbose_name_plural = 'Fragen'
Die Einträge hätte ich im Admintool geren sortiert. Was mache ich den hier wieder verkehrt:

Code: Alles auswählen

class FrageAdmin(admin.ModelAdmin):
    ordering: ["kategorie", "typ", "typ2"]
Hier funktioniert das prima:

Code: Alles auswählen

class OrtAdmin(admin.ModelAdmin):
    ordering = ['plz',]
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

vergleich' doch mal ganz genau deine beiden Beispiele... besonders das Zeichen, das nach `ordering` steht...

Zum Modell: `typ` und `typ2` ist kryptisch, erst recht wenn es Integerwerte sind. Das spricht dann stark dafür, dass das Fremdschlüssel sein sollten, weil doch irgendwo bestimmt ein Mapping existiert, dass z.B. `typ=1` bedeutet `typ=Prozentrechnung`.

`titel` und `text` mit `blank=True`? Wäre eine Frage ohne Frage... macht irgendwie keinen Sinn.

Und irgendwie fehlt auch die Zuordnung zu einer Antwort für die Frage.

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

"Ist der Ruf erst ruiniert, lebt es sich ganz ungeniert"

irgendwie kann ich mich hier wahrscheinlich nicht mehr wirklich blamieren (Hier gibt es imme noch kein Smiley für Schämen).
Aber im Ernst:
1. Gut, dass wir drüber gesprochen haben, die 'blanc=True' machen hier keinen Sinn - die kommen aus einer Zeit, wo ich mich noch blöder angestellt habe.
2. Zu den Fragen gehören ja immer irgendwelche Werte, die im Protokoll gespeichert werden. Und auch die Ergebnisse sind ja meistens Werte (können z.B. aber auch Strings mit Termen oder Begriffen sein). Die sind auch im Protokoll.
3. Die Felder typ und typ2 sind keine Fremdschlüssel, das sind Unterkategorien. Zum Beispiel bei Geometrie können das vollkommen verschiedene Aufgabestellungen sein: Werte im Koordinatensystem, Benennungen an Figuren oder Körpern, Fläche oder Umfang von Figuren usw.. Diese habe ich manchmal auch noch in weitere Unterunterkategorien unterteilt (zum Beispiel Aufgaben zu Parallele und Senkrechte oder auch verschiedene Textformulierungen für verschiedene Schwierigkeitsgrade).

Danke für die Hinweise!

Ach ja, bei der Gelegenheit:
Ich hatte ja gedacht, dass meine Datenbank kleiner wird, wenn ich die Felder für diese Texte lösche - ist sie aber nicht - ganz im Gegenteil, sie ist von 47 656kB auf 86 076kB angewachsen. Kann das jemand erklären?
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

@Pitzwheazle: Warum dürfen das denn dann keine Fremschlüssel sein? Wenn es eine Tabelle mit "Kategorien" gibt, muss natürlich der Fremdschlüssel mit dem Verweis auf die Kategorie dort eingetragen werden. Ich würde sagen, es drängt sich regelrecht auf. Was soll denn da sonst drin stehen?
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Der Fremdschlüssel müsste aber doch irgendwo hinzeigen - wo sollte das den sein? Das verstehe ich nicht. Das Feld "kategorie" hat doch einen Fremdschlüssel.
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Was ist denn "typ" und "typ". Das geht ja aus den Namen nicht hervor. Du hast geschrieben, dass es Unterkatergorien sind. Also sollte es doch auch eine Relation mit Unterkategorien geben?
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Vielleicht habe ich ja einen vollkommen blöden Ansatz, aber ich will es mal an einem Beispiel aufzeigen. In diesen Untertypen werden teilweise vollkommen verschiedene Aufgaben zu einer Aufgabenkategorie, wie der geschilderten zu "Geometrie" erzeugt. Da ist der Code ziemlich lang. An meiner neuesten Kateglorie "Gleichungen" kann ich das aber aufzeigen, wenn ich da die ganzen Hilfetexte rausnehme ist der Code sehr kurz und erzeugt nur verschiedene Gleichungen:

Code: Alles auswählen

        if aufgnr < 6:
            typ = random.randint(typ_anf, 4) 
        else:
            typ = random.randint(typ_anf, typ_end+stufe%2) 
        titel = "Gleichungen" 
        frage = "x="
        variable = ["",]
        pro_text = einheit = anmerkung =  ""
        erg = random.randint(1,9)
        absolut = 0
        while absolut == 0:
            absolut = random.randint(-4,4)
        koeff1 = random.randint(2,5)
        if typ == 1:
            pro_text = "{}x = {}"
            variable = [koeff1,koeff1*erg] 
            hilfe_id = 10
        elif typ == 2:
            pro_text = "x{:+d} = {}"
            variable = [absolut,absolut+erg]
            if absolut >1: 
                hilfe_id = 21
            else:
                hilfe_id = 22
        elif typ == 3:
            pro_text = "{}x{:+d} = {}"
            variable = [koeff1,absolut,koeff1*erg+absolut]
            if absolut >1: 
                hilfe_id = 31
            else:
                hilfe_id = 32
        elif typ == 4:
            pro_text = "{}{:+d}x = {}"
            variable = [absolut,koeff1,koeff1*erg+absolut]
            if absolut >1: 
                hilfe_id = 41
            else:
                hilfe_id = 42
        elif typ == 5:
            pro_text = "{} = {}x{:+d}"
            variable = [koeff1*erg+absolut,koeff1,absolut]
            if absolut >1: 
                hilfe_id = 51
            else:
                hilfe_id = 52
        elif typ == 6:
            koeff2 = koeff1
            while koeff2 == koeff1:
                koeff2 = random.randint(2,5) 
            zwischen = (koeff1-koeff2)*erg+absolut           
            pro_text = "{}x{:+d} = {}x{:+d}"
            variable = [koeff2,zwischen,koeff1,absolut]
            hilfe_id = 61
        elif typ == 7:
            koeff2 = koeff1
            while koeff2 == koeff1:
                koeff2 = random.randint(2,5) 
            zwischen = (koeff1*erg+absolut)*koeff2
            pro_text = "{}({}x{:+d}) = {}"
            variable = [koeff2,koeff1,absolut,zwischen,-1*absolut]
            if stufe%2 == 1:
                hilfe_id = 71
            else:
                if absolut > 0:
                    hilfe_id = 72
                else:
                    hilfe_id = 73
        text = "Löse folgende Gleichung <br>" + pro_text
Das ist aber sicher der kürzeste Code für verschiede Untertypen. Kann man da irgendwelche Fremdschlüssel draus machen? (Und warum?)
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Das versteht doch niemand! Was sollen denn die hilfe_id? Kryptische Nummern, benutzt man nicht.
Wenn Du für jede Frage extra Code brauchst, warum willst Du dann die Fragen in die Datenbank stecken?

Und wir waren doch schon mal viel weiter, als Du Gleichungen generisch definiert hast, und Werte automatisch erzeugt hast und die Lösung automatisch bewertet hast.

Statt also alles auszuprogrammieren definiert man sich passende Datenstrukturen.
Ein Aufgabentyp wird durch einen Aufgabentext-Template, einen Hilfetext, eine Funktion zum generieren der Variablen und eine Funktion zum Prüfen der Richtigkeit definiert.

Daneben gibt es Datenstrukturen, die Aufgabentypen zu Kategorien zusammenfassen und Datenstrukturen, die Jahrgangsstufen Aufgabentypen zuordnet.

Im Moment hast Du alles kreuz und quer definiert, so dass man da nicht durchblickt.
Pitwheazle
User
Beiträge: 873
Registriert: Sonntag 19. September 2021, 09:40

Wahrscheinlich redne wir dauernd aneinander vorbei. Vielleicht müsstest du dir erst mal anschauen, wie mein www.rechentrainer.app überhaupt aussieht - oder sogar meinen Code auf GitHub.
Ich habe mir viel Mühe gegeben und kann es wahrscheinlich nicht besser ... und mein Programm funktioniert ja auch.
Das versteht doch niemand! Was sollen denn die hilfe_id? Kryptische Nummern, benutzt man nicht.
nachdem ihr mir immer wieder erklärt, ich solle die Möglichkeiten der relationalen Datenbank nutzen und nicht alles in mein Protokoll packen, habe ich die Hilfetxte in einer extra Tabelle(?) gespeichert. Im Protokoll steht die ID und unter dieser findet man den Text in der Tabelle "Hilfe". Vorher habe ich sie in meinem Code und im Protokoll gespeichert - das war einfacher für mich. Die ID entspricht größtenteils dem Unter"typ" und ist noch aufgeteilt für gute und nicht so fitte Schüler und Schülerinnen.
Wenn Du für jede Frage extra Code brauchst, warum willst Du dann die Fragen in die Datenbank stecken?
Wollte ich eigentlich nicht - ich hatte deine Vorschläge so interpretiert.
Und wir waren doch schon mal viel weiter, als Du Gleichungen generisch definiert hast, und Werte automatisch erzeugt hast und die Lösung automatisch bewertet hast.
Ist das nicht mehr so?
Statt also alles auszuprogrammieren definiert man sich passende Datenstrukturen.
Ein Aufgabentyp wird durch einen Aufgabentext-Template, einen Hilfetext, eine Funktion zum generieren der Variablen und eine Funktion zum Prüfen der Richtigkeit definiert.
Damit bin ich überfordert, ich habe zwar die Prinzipien des objektorientierten Programmierens oft gelesen und auch möglicherweise grundsätzlich verstanden - bin aber nicht in der Lage, das in meinem Programm umzusetzen.
Daneben gibt es Datenstrukturen, die Aufgabentypen zu Kategorien zusammenfassen und Datenstrukturen, die Jahrgangsstufen Aufgabentypen zuordnet.
Ich glaube, das entspricht nicht dem Aufbau meines Programms. Vielleicht schaust du es dir mal an. Ich bin gerne bereit dazuzulernen, schaffe das aber halt nur begrenzt.
Im Moment hast Du alles kreuz und quer definiert, so dass man da nicht durchblickt.
Das liegt garantiert daran, dass du(ihr das ganze Projekt anders angegeangen wärt. ich habe ja schon ein fertiges Programm (www.rechen.trainer.schule), dass ich jetzt zu einem größten Teil "übersetzt" habe, damit es auf Tablets und Smartphones läuft.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

kann es sein, dass der Name "typ" einfach schlecht gewählt ist und das vielleicht besser " schwierigkeitsgrad" heißen sollte?

Und wofür steht eigentlich "pro_text"? So wie das aussieht ist das doch ein Template für die Gleichung?

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

noisefloor hat geschrieben: Samstag 27. Januar 2024, 09:29 kann es sein, dass der Name "typ" einfach schlecht gewählt ist und das vielleicht besser " schwierigkeitsgrad" heißen sollte?
Nein, mit den Schwierigkeitsgraden hat es nichts zu tun. Allerdings müssen die Kids immer mehr der Unter"typ"en erledigen wenn sie in höhere Jahrgangsstufen kommen. Zum besseren Verständnis habe ich hier mal die Überschriften zur Kategorie "Geometrieaufgaben" kopiert:

Code: Alles auswählen

if typ == 1:                                #Parallel und Senkrechte
   if typ2 == 1:                            #g parallel
	elif typ2 == 2:                         #h parallel
	elif typ2 == 3:                         #Senkrechte
	else:                                   #Senkrechte
elif typ == 2:                              #Begriffe: Strecke usw.
	if typ2 == 1:                           #Strecke
	elif typ2 == 2:                         #Gerade
	elif typ2 == 3:                         #Gerade durch zwei Punkte
	elif typ2 == 4:                         #Strahl
elif typ == 3:                              #Figuren
elif typ == 4:                              #A und u zusammengestzte Figuren
	if typ3 == 1:
	elif typ3  == 2:
	elif typ3 == 3:
	else:
	typ2 = random.randint(1,2)
	if typ2 == 1:							# Umfang
	else:									# Fläche
elif typ == 5:                              #Körper - ruft eine Funktion zur Darstellung verscheidener Körper auf
	titel = "Grundformen der Geometrie"
	text = "Wie heißt dieser Körper?"
elif typ == 6:                              #räumliches Vorstellungsvermögen
	titel = "Räumliches Vorstellungsvermögen"
	text = "Ups, bei diesem Würfel sind ein paar Bausteine verlorengegegangen.<br>Wieviele sind es?"
elif typ == 7:                              #Koordinaten
	if typ2 ==1:                            #nur N im 1.Quadranten
	elif typ2 ==2:                          #nur Kommazahlen im 1.Quadranten
	else:   #Koordinatensystem
elif typ == 8:                              #Symmetrie
	if typ5 < 0.4:
		text = "Wieviele dieser {0} haben {1} Symetrieachse{2}?<br><br>{3}".format(auswahl, anzahl_frage[typ4], endung, zeichen_liste[typ3])
		erg = anzahl_achsen[typ3][typ4]
	elif typ5 < 0.6:
		text = "Wieviele dieser {0} sind punktsymetrisch?<br><br>{2}".format(auswahl,anzahl_frage[typ4],zeichen_liste[typ3])
		erg = anzahl_punkt[typ3]
	elif typ5 < 0.95:
		text = "{0}Wieviele dieser Vierecke besitzen {1} Symetrieachse{2}?".format(familie, anzahl_frage[typ4], endung)
		erg = familie_achsen[typ4]
	else:
		text = "{0}Wieviele dieser Vierecke sind punktsymetrisch?".format(familie)
		erg = 3
elif typ == 9:                              #Achsspiegelung
	if typ2 == 1:                           #nur positive Zahlen
	else:                                   #auch negative Zahlen
	if typ3 == 1:                           #Spiegelachse ist Winkelhalbierende
	elif typ3 == 2:                         #Spiegelachse parallel zur y-Achse
	elif typ3 == 3:                         #Spiegelachse parallel zur x-Achse
else:                                       #10 Name Dreiecke - 11 Namen und Seiten Ecken
noisefloor hat geschrieben: Samstag 27. Januar 2024, 09:29 Und wofür steht eigentlich "pro_text"? So wie das aussieht ist das doch ein Template für die Gleichung?
Die Nutzer und ihre Lehrkräfte können eine Protokollseite aufrufen ind der jede einzelne aufgerufene Aufgabe des/der Schülers/in steht. Damit jede Aufgabe in eine Zeile passt, erstelle ich bei langen Texten einen kürzeren Text - nur für diese Protokollseite.
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

Pitwheazle hat geschrieben: Freitag 26. Januar 2024, 22:41 Wahrscheinlich redne wir dauernd aneinander vorbei. Vielleicht müsstest du dir erst mal anschauen, wie mein www.rechentrainer.app überhaupt aussieht - oder sogar meinen Code auf GitHub
Könntest du diesen Link, sowie den Link zu Github, bitte in dein Profil oder deine Signatur stellen, damit man sie immer schnell finden kann? Das wird ja bei vielen deiner Fragen relevant. Danke! :mrgreen:
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.
Antworten