wo liegt jetzt wieder mein Fehler?

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

Jetzt habe ich das mit der kategorie_id gelöst, jetzt funktioniert was anderes nicht.
In meinem Protokoll halte ich jede Aufgabe fest und zusätzlich protokolliere ich die Eingabe je user und Kategorie in "Zaehler". Darauf konnte ich auch immer prima zugreifen (in meiner template "details.html"). Jetzt klappt der Zugriff auf "Zaehler" nicht mehr und ich finde den Fehler nicht:
Meine Funktion:

Code: Alles auswählen

def details(req, zeile_id):
    protokoll = Protokoll.objects.get(pk = zeile_id)
    try:
        hilfe = Hilfe.get_object_or_404(kategorie = protokoll.kategorie, lfd_nr = protokoll.hilfe)
    except:
        hilfe = ""
    print(protokoll.user)
    print(protokoll.kategorie)
    try:
        zaehler = Zaehler.get_object_or_404(user = protokoll.user, kategorie = protokoll.kategorie)
    except:
        zaehler = "nicht gefunden!"
    print(zaehler)
    return render(req, 'core/details.html', {'protokoll': protokoll, 'zaehler': zaehler, 'hilfe': hilfe})
print gibt:

Code: Alles auswählen

(Franz Musterschüler, 5.1)
erganzen
nicht gefunden!
zurück. Der Eintrag zu "Franz Musterschüler" und "erganzen" existiert aber:
Bild
Das model "Zaehler":

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")
    ...
... an dem fehlenden "ä" liegt es auch nicht. Einerseits klappt es mit den anderen Kategorien auch nicht und gestern ging es noch. Ich sehe keinen Zusammenhang darin, dass ich das mit der "kategorie_id" geändert habe?
Sirius3
User
Beiträge: 17809
Registriert: Sonntag 21. Oktober 2012, 17:20

Natürlich findest du den Fehler nicht, weil du alles, was dazu dienen könnte, ihn zu verstehen wegschmeißt und statt dessen nur ein nichtssagendes "nicht gefunden" ausgibt.
Man darf niemals ein nackte except benutzen, und nur die Fehler abfangen, die man an def Stelle auch erwarten würde. Zumindest aber schreibt man den kompletten Traceback in die log-Datei.
Pitwheazle
User
Beiträge: 907
Registriert: Sonntag 19. September 2021, 09:40

Auweh, ob ich das irgendwann mal alles lerne?
Hilft das weiter:

Code: Alles auswählen

Exception Value: 	

type object 'Zaehler' has no attribute 'get_object_or_404'

Exception Location: 	D:\Dropbox\RechentrainerWeb\rechentrainer Kopie (1)\core\views.py, line 2749, in details
und die entsprechenden Zeile lautet natürlich:

Code: Alles auswählen

zaehler = Zaehler.get_object_or_404(user = protokoll.user, kategorie = protokoll.kategorie)
Zumindest aber schreibt man den kompletten Traceback in die log-Datei.
... wie mache ich das?
Benutzeravatar
noisefloor
User
Beiträge: 3879
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

lies' dir mal die Doku zu `get_object_or_404`durch (https://docs.djangoproject.com/en/4.1/t ... ect-or-404), dann solltest du sehen, dass du es falsch verwendest. `get_object_or_404` ist keine Methode eines Models.

Gruß, noisefloor
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Du brauchst get_object_or_404 (auch richtig benutzt) gar nicht, da du den Fehler ja abfängst und gar keine 404 Seite auslieferst. Ich rate mal, dass deine Hilfe auch immer leer ist?

Hier tut es in beiden fällen ein:

Code: Alles auswählen

try:
    hilfe = Hilfe.objects.get(kategorie = protokoll.kategorie, lfd_nr = protokoll.hilfe)
except Hilfe.DoesNotExist:
    hilfe = ""
Mit Zaehler dann entsprechend.

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

noisefloor hat geschrieben: Samstag 19. November 2022, 17:46 lies' dir mal die Doku zu `get_object_or_404`durch (https://docs.djangoproject.com/en/4.1/t ... ect-or-404), dann solltest du sehen, dass du es falsch verwendest. `get_object_or_404` ist keine Methode eines Models.
Ich muss hier mal wieder feststellen, dass ich mit dem Verständnis der Doku überfordert bin, Das hat wohl auch nichts damit zu tun, ob man der englischen Sprache mächtig ist. Ich kann mich erinnern, dass mir in einem meiner unzähligen Postings geraten wurde, beim Zugriff auf meine Tabellen "get" durch "get_object_or_404" zu ersetzen, da ansonsten ein Fehler entsteht, falls es mehrere Object ergibt (Was in meinem Code eigentlich nicht vorkommen sollte). Dabei habe ich anscheinend den Code falsch angewendet. Jetzt habe ich:

Code: Alles auswählen

zaehler = Zaehler.get(user = protokoll.user, kategorie = protokoll.kategorie)
durch:

Code: Alles auswählen

zaehler = get_object_or_404(Zaehler, user = protokoll.user, kategorie = protokoll.kategorie)
    #zaehler = Zaehler.get(user = protokoll.user, kategorie = protokoll.kategorie)
ersetzt - jetzt klappt es wieder.
Whitie hat geschrieben: Sonntag 20. November 2022, 08:29 Du brauchst get_object_or_404 (auch richtig benutzt) gar nicht, da du den Fehler ja abfängst und gar keine 404 Seite auslieferst. Ich rate mal, dass deine Hilfe auch immer leer ist?
Nein, meine Hilfe ist natürlich nicht immer leer. Ich hatte in einem anderen Posting beschrieben, dass ich die Hilfetexte in eine eigene Datenbank ausgelagert habe, damit nicht so viel Datenmüll entsteht, da ansonsten in jedem Protokolleintrag der entsprechende komplette Hilfetext gespeichert ist. Die Schülerinnen und Schüler rufen diesen erfahrungsgemäß nicht so oft auf und der Text kann u.U. ziemlich lang werden. Den Hilfetexten weise ich eine Nummer zu und hier kann es zurzeit noch zu Fehlern kommen, dass eine aufgerufene Zahl nicht vorhanden ist. Das wollte ich abfangen.
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Pitwheazle hat geschrieben: Sonntag 20. November 2022, 11:41 Ich muss hier mal wieder feststellen, dass ich mit dem Verständnis der Doku überfordert bin, Das hat wohl auch nichts damit zu tun, ob man der englischen Sprache mächtig ist. Ich kann mich erinnern, dass mir in einem meiner unzähligen Postings geraten wurde, beim Zugriff auf meine Tabellen "get" durch "get_object_or_404" zu ersetzen, da ansonsten ein Fehler entsteht, falls es mehrere Object ergibt (Was in meinem Code eigentlich nicht vorkommen sollte).
Du lieferst aber keinen 404 Fehler aus, die Funktion hilft dir hier nicht. Und ich zitiere mal aus der oben verlinkten Dokumentation:
Note: As with get(), a MultipleObjectsReturned exception will be raised if more than one object is found.
Also, wer auch immer dir das geraten hat, hatte bestimmt etwas anderes im Sinn oder die Doku nicht komplett gelesen. Genau der Fehler den du umgehen möchtest, tritt mit get_object_or_404 auch auf.

Lösung wäre:

Code: Alles auswählen

from django.core.exceptions import MultipleObjectsReturned

try:
    zaehler = Zaehler.objects.get(user = protokoll.user, kategorie = protokoll.kategorie)
except Zaehler.DoesNotExist:
    zaehler = "nicht gefunden"
except MultipleObjectsReturned:
    zaehler = "mehr als ein Objekt gefunden"
Allerdings sind mehrere Objekte im laufenden Betrieb kritisch. Wie willst du damit umgehen? Das wird dann auch noch an anderen Stellen krachen.
Falls das doch vorkommen kann, welcher ist dann der "richtige" Zähler?
Wenn es egal wäre:

Code: Alles auswählen

zaehler = Zaehler.objects.filter(user = protokoll.user, kategorie = protokoll.kategorie).first()
Pitwheazle hat geschrieben: Sonntag 20. November 2022, 11:41 Nein, meine Hilfe ist natürlich nicht immer leer.
...
Ich meinte damit, du hättest dir in deinem Ursprungscode die Variable "hilfe" auch mal ausgeben lassen sollen. Durch die falsche Benutzung von get_object_or_404 wäre sie immer leer gewesen. Vielleicht wärst du dann schneller dem Rätsel auf die Spur gekommen ;-)

Viele Grüße
Whitie

Edit: Ich würde den MultipleObjectsReturned Fehler nicht abfangen. Wenn der auftritt ist wirklich was kaputt und darum muss sich gekümmert werden.
Pitwheazle
User
Beiträge: 907
Registriert: Sonntag 19. September 2021, 09:40

OK, danke. Ich denke, ich werde verhindern, das jeweils mehrere Objekte gefunden werden.
Aber, wenn wir schon darüber sprechen: Meine Hilfen versehe ich mit Nummern, die nunmal nicht mehrmals vorkommen dürfen. Ich wollte jetzt im Nachhinein den Eintrag:

Code: Alles auswählen

 lfd_nr = models.SmallIntegerField(default=0)
mit

Code: Alles auswählen

 lfd_nr = models.SmallIntegerField(default=0), unique=True
ergänzen.
"makemigration" ging noch, "migrate" meldete einen Fehler, den ich nur durch Rückgängigmachen der migrations wieder beheben konnte - was besseres fiel mir nicht ein. Kann man dieses "unique=True" nicht nachträglich einfügen?
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Die Fehlermeldung wäre interessant...
Pitwheazle
User
Beiträge: 907
Registriert: Sonntag 19. September 2021, 09:40

Nun gut. Dann muss ich das nochmal ändern. Wenn ich die Änderung aber dann rückgängig mache, mault meine IDE bei "runserver", dass nicht durchgeführte migrations vorlägen.
Pitwheazle
User
Beiträge: 907
Registriert: Sonntag 19. September 2021, 09:40

Running migrations:
Applying core.0062_alter_hilfe_lfd_nr...Traceback (most recent call last):
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\sqlite3\base.py", line 416, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: UNIQUE constraint failed: new__core_hilfe.lfd_nr

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "D:\Dropbox\RechentrainerWeb\rechentrainer Kopie (1)\manage.py", line 22, in <module>
main()
File "D:\Dropbox\RechentrainerWeb\rechentrainer Kopie (1)\manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\management\__init__.py", line 425, in execute_from_command_line
utility.execute()
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\management\__init__.py", line 419, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\management\base.py", line 373, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\management\base.py", line 417, in execute
output = self.handle(*args, **options)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\management\base.py", line 90, in wrapped
res = handle_func(*args, **kwargs)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\management\commands\migrate.py", line 253, in handle
post_migrate_state = executor.migrate(
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\migrations\executor.py", line 126, in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\migrations\executor.py", line 156, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\migrations\executor.py", line 236, in apply_migration
state = migration.apply(state, schema_editor)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\migrations\migration.py", line 125, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\migrations\operations\fields.py", line 225, in database_forwards
schema_editor.alter_field(from_model, from_field, to_field)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\sqlite3\schema.py", line 140, in alter_field
super().alter_field(model, old_field, new_field, strict=strict)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\base\schema.py", line 618, in alter_field
self._alter_field(model, old_field, new_field, old_type, new_type,
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\sqlite3\schema.py", line 362, in _alter_field
self._remake_table(model, alter_field=(old_field, new_field))
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\sqlite3\schema.py", line 285, in _remake_table
self.execute("INSERT INTO %s (%s) SELECT %s FROM %s" % (
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\base\schema.py", line 151, in execute
cursor.execute(sql, params)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\utils.py", line 99, in execute
return super().execute(sql, params)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\utils.py", line 67, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\utils.py", line 76, in _execute_with_wrappers
return executor(sql, params, many, context)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\utils.py", line 80, in _execute
with self.db.wrap_database_errors:
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\Pit\AppData\Local\Programs\Python\Python310\lib\site-packages\django\db\backends\sqlite3\base.py", line 416, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: UNIQUE constraint failed: new__core_hilfe.lfd_nr
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Hast du in der DB Datensätze, die den Defaultwert (0) haben? Man könnte null=True und default=None (wir zu NULL in der DB) setzen, denn NULL in der DB wird bei UNIQUE constraints nicht beachtet. Oder man setzt vor der Migration alle Felder manuell auf verschiedene Werte, dann sollte es auch funktionieren (hab es aber nicht ausprobiert).
Pitwheazle
User
Beiträge: 907
Registriert: Sonntag 19. September 2021, 09:40

Ich habe da wieder einen Denkfehler gemacht. Innerhalb der Kategorien gibt es keine Doppel ansonsten schon - musste ich feststellen.
Antworten