Fehlender Tabellenname in IntegrityError (Django ORM)

8

Ich vermisse den Tabellennamen in IntegrityError von Django:

%Vor%

Gibt es eine Möglichkeit zu sehen, auf welche Tabelle das INSERT / UPDATE zugreift?

Wir verwenden PostgreSQL 9.6.

Dies ist eine allgemeine Frage : Wie erhalte ich eine bessere Fehlermeldung?

Dies ist keine Frage zu dieser bestimmten Spalte. Ich fand die relevante Tabelle und Spalte sehr bald. Aber ich möchte die Fehlermeldung verbessern, die von unserem CI-System kommt. Das nächste Mal möchte ich den Tabellennamen sofort sehen.

Ich weiß, dass ich die fehlenden Informationen leicht mit einem Debugger aufdecken kann, wenn ich diesen Fehler während der Softwareentwicklung sehe. Aber in meinem Fall passiert das in der Produktion, und ich habe nur den Stack-Trace wie oben.

    
guettli 10.10.2017, 07:41
quelle

7 Antworten

5

Die Ausnahmebedingungsnachricht in diesem Traceback ist die ursprüngliche Nachricht aus dem Datenbanktreiber. Es ist nützlich, dies und die Rückverfolgung zu wissen, wenn etwas gegoogelt, gemeldet wird usw.

Die Ausnahmeklasse ist für alle Backends gleich django.db.utils. IntegrityError , aber die Nachricht bzw. die Argumente hängen vom Backend ab:

  • postgres : null value in column "manager_slug" violates not-null constraint\n DETAILS...\n
  • mysql . : (1048, "Column 'manager_slug' cannot be null")
  • sqlite3 . : NOT NULL constraint failed: appname_modelname.manager_slug

Der Tabellenname ist nur mit sqlite3 backend sichtbar. Einige Backends verwenden nur das Argument string der Ausnahme, aber mysql verwendet zwei Argumente: einen numerischen Fehlercode und eine Nachricht. (Ich möchte akzeptieren, dass es sich um eine allgemeine Frage handelt, nicht nur PostgreSQL.) Autoren einiger Backends erwarten, dass der Autor der App den Tabellennamen direkt oder aus SQL kennt, aber nicht mit allgemeinen ORM-Paketen. Es gibt keinen vorzuziehenden und allgemein akzeptierten Weg, wie man die Nachricht ausdehnt, selbst wenn sie technisch perfekt gemacht werden kann.

Entwicklung und Debugging sind einfach:

  • Viele zusätzliche Informationen sind im DEBUG-Modus in der Entwicklung verfügbar ("SQL" im letzten Frame oder ein Klassenname eines Objekts in einer Zeile wie "myobj.save ()")
  • python manage.py test --debug-sql : "Druckt protokollierte SQL-Abfragen bei Fehlern."
  • Der gleiche Fehler in der Entwicklung / Tests mit sqlite3 ist leichter lesbar.

... aber Sie fragen wahrscheinlich nach einem Laufzeitfehler in der Produktion.

Ich denke über Ihre mögliche Absicht in einer so allgemeinen Frage nach, welche Richtung für Sie interessant sein könnte.

A) Die wichtigsten Informationen aus dem traceback sind normalerweise einige Zeilen oberhalb die vielen Zeilen mit "... / django / db /...". Es ist vollkommen einfach für einen Guru. Es kann sehr wahrscheinlich verwendet werden, wenn der Code nicht so dynamisch und allgemein wie eine Django Admin-Site ist, wo kein Code in der Nähe von myobj.save() call (weder in Eltern-Frames) noch einen expliziten Modellnamen enthält. Beispiel:

%Vor%

B) Fangen Sie die Informationen mit einem gemeinsamen Vorfahren Ihrer Modelle ab

%Vor%

Dies könnte das Debugging mit Mehrfachvererbung erschweren.

C) Eine Implementierung in Django db wäre besser, aber ich kann mir nicht vorstellen, dass sie akzeptiert wird und nach einem Problem nicht wieder rückgängig gemacht wird.

    
hynekcer 11.10.2017, 01:21
quelle
2

Wenn Sie SQL Funktion erstellen können Sie versuchen:

create function, um den letzten Sequenzwert zu erhalten get_sequence_last_value ( ursprünglicher Post )

%Vor%

nachdem es eine Tabelle mit der Sequenz mehr als im Fehler-Stack bekommen hat und die Spalte manager_slug

hat %Vor%

Ich verstehe, dass die Lösung nicht voll ist, aber ich hoffe, dass es Ihnen helfen kann

    
Bear Brown 13.10.2017 14:12
quelle
2

Ich würde vorschlagen, Sentry ( Ссылка ) zu verwenden. In Sentry Issues können Sie alle lokalen Variablen für alle Teile eines Stack-Trace beobachten.

    
Trilliput 17.10.2017 19:54
quelle
2

Die beste Lösung, die ich für Ihr Problem gefunden habe, ist die DataBaseErrorWrapper Methode zu überschreiben, dazu gehen Sie zu \django\db\utils.py und in der Zeile 86 ersetzen Sie dj_exc_value = dj_exc_type(*exc_value.args) für:

%Vor%

und wenn der IntegrityError erscheint, sollte die Nachricht funktionieren

%Vor%

Ich bin mir nicht sicher, aber das sollte mit diesen Ausnahmen funktionieren:

%Vor%

Es funktioniert für mich, sag mir, ob dir das funktioniert. Denken Sie daran, bearbeiten Sie die Datei mit dem Django-Ordner, den Sie gerade arbeiten

    
Mauricio Cortazar 18.10.2017 17:32
quelle
0

Sie haben den gesetzten Wert in der Spalte "manager_slug" verfehlt. Sie können für diese Spalte keinen NULL-Wert festlegen. Sie sollten Wert festlegen oder Nicht-Null-Bedingung entfernen.

%Vor%     
Zheka Koval 10.10.2017 07:45
quelle
0
  

Gibt es eine Möglichkeit zu sehen, auf welche Tabelle das INSERT / UPDATE zugreift?

Wenn Sie migrate ausführen, können Sie einfach die Standardausgabe aufrufen und prüfen, welche Migration ausgeführt wird. Dann können Sie die Migrationsdatei öffnen und einen besseren Überblick über das Problem haben.

Wenn Sie nicht glauben, dass Sie sich ansehen möchten PEP249 zur optionalen Fehlerbehandlung. als django Datenbank Wrapper basiert auf PEP249 Spezifikation.

Referenzen zu Django-Code innerhalb von DatabaseErrorWrapper

2. EDIT:

Sie konnten den Integritätsfehler abfangen und auf das .messages -Attribut vom Datenbank-Wrapper zugreifen.

Pseudo Beispiel:

%Vor%     
efkin 17.10.2017 09:45
quelle
0

Ich neige dazu, so wenig Abhängigkeit wie möglich zu verwenden und die Bibliotheken von Drittanbietern so zu belassen, wie sie sind.

In den meisten Fällen würde ich jede sql einfügen / aktualisieren / löschen Abfrage protokollieren. Auf diese Weise kann ich leicht erkennen, welche Abfrage ohne zusätzlichen Aufwand fehlgeschlagen ist. Dies ermöglicht mir zu verfolgen, wer was wann in meinem System getan hat.

Dies erfüllt einen Teil der gesetzlichen Anforderungen für die Verfolgung von Maßnahmen in meiner Branche.

    
Diansheng 20.10.2017 02:42
quelle