Django: Integritätsfehler abfangen und mithilfe der Vorlage eine benutzerdefinierte Nachricht anzeigen


76

In meiner Django-App gibt es nur einen offensichtlichen Fall, in dem "IntegrityError" auftreten kann.
Wie kann ich diesen Fehler abfangen und eine Nachricht mithilfe von Vorlagen anzeigen?

Antworten:


156

Verwenden Sie einfach try and catch.

from django.db import IntegrityError
from django.shortcuts import render_to_response

try:
    # code that produces error
except IntegrityError as e:
    return render_to_response("template.html", {"message": e.message})

Wenn Sie möchten, können Sie die Nachricht in Ihrer Vorlage verwenden.

BEARBEITEN

Vielen Dank für Jill-Jenn Vie , sollten Sie nutzen e.__cause__, wie hier beschrieben .


Vielen Dank, ich konnte nicht herausfinden, warum "aus MySQLdb IntegrityError importieren" nicht den Trick machte. Der Aufrufstapel schien zu zeigen, dass die Bibliothek den Fehler ausgelöst hat, aber irgendwie wird er in die Datei django.db verschoben. Grr.
Julian

3
Wie in den Dokumenten von Version 1.6 ausgeführt , e.__cause__wird gemäß PEP 3134 bevorzugt .
Jill-Jênn Vie

1
Wenn Sie keine Nachricht erhalten, versuchen Sie dies: e.args
Jay Modi

e.message hat bei mir nicht funktioniert, aber e.args [1] hat den Job gemacht
Edgar Navasardyan

@blissini - Ich habe den Link geändert, um auf die Entwicklerdokumentation zu verweisen
Tony

11

Wenn Sie mit dem CreateViewMixin klassenbasierte Ansichten verwenden , möchten Sie beispielsweise trydie Oberklasse aufrufen form_valid:

from django.db import IntegrityError
...
class KumquatCreateView(CreateView):
    model = Kumquat
    form_class = forms.KumquatForm
    ...
    def form_valid(self, form):
        ...
        try:
            return super(KumquatCreateView, self).form_valid(form)
        except IntegrityError:
            return HttpResponse("ERROR: Kumquat already exists!")

Sie können render_to_responsenatürlich eine Vorlage usw. verwenden, um die Ausgabe zu verbessern.


3

Einfachste Lösung: Schreiben Sie eine Middleware-Implementierung process_exception, die nur IntegrityError abfängt und eine HttpResponse mit Ihrer gerenderten Vorlage zurückgibt, und stellen Sie sicher, dass diese Middleware nach dem Standardfehler bei der Behandlung von Middleware liegt, sodass sie zuvor aufgerufen wird (siehe https://docs.djangoproject.com/de) / dev / topic / http / middleware / # Prozessausnahme für mehr).

Wenn ich Sie wäre, würde ich nicht davon ausgehen, dass "es nur einen offensichtlichen Fall gibt, in dem" IntegrityError "auftreten kann". Ich empfehle daher dringend, die Ausnahme in Ihrer Middleware zu protokollieren (und E-Mail-Benachrichtigungen zu senden).


Durch das Einfügen in die Middleware wird nicht nur der Fehler in der App, sondern in allen Apps im Projekt abgefangen.
Chris Wesseling

@ChrisWesseling: Stimme voll und ganz zu, deshalb habe ich erwähnt, dass "ich so etwas nicht annehmen würde", dass es nur einen offensichtlichen Fall gibt, in dem "IntegrityError" auftreten kann "
bruno desthuilliers

1
Waffen schießen keine Menschen in den Fuß, Menschen schießen Menschen in den Fuß. :-)
Chris Wesseling

Ich würde es nicht die einfachste Lösung nennen, aber es ist eine nützliche Alternative, über die man Bescheid wissen sollte. Vielen Dank.
Spinkus

1

Ich würde es mit ModelForm validieren. Zum Beispiel:

Du hast Modell:

class Manufacturer(models.Model):
    name = models.CharField(default='', max_length=40, unique=True)

Und ModelForm:

class ManufacturerForm(forms.ModelForm):

    def clean(self):
        cleaned_data = super(ManufacturerForm, self).clean()
        name = cleaned_data.get('name')
        if Manufacturer.objects.filter(name=name).exists():
            raise forms.ValidationError('Category already exists')

    class Meta:
        model = Manufacturer

In diesem Fall, wenn Sie einen eindeutigen Namen angeben. Vor IntegrityError wird ein Validierungsfehler angezeigt. Die Meldung "Kategorie existiert bereits" wird in Ihrem Formular in der Vorlage angezeigt


0

Ich habe es so gemacht

from django.db import IntegrityError
from django.shortcuts import render

from .models import Person
from .forms import PersonForm

class PersonView(View):

def get(self, request):
    pd = PersonForm()
    return render(request, "app1/my_form.html", context={ 'form': pd })



def post(self, request):
    pd = PersonForm(request.POST)


    if pd.is_valid():
        name = pd.cleaned_data['name']
        age = pd.cleaned_data['age']
        height = pd.cleaned_data['height']

        p = Person()
        p.name = name
        p.age = age
        p.height = height
        try:
            p.save()
        except IntegrityError as e:
            e = 'this data already exists in the database'
            return render(request, "app1/my_form.html", context={ 'form': pd, 'e': e})

        context = {
        'person': {
            'name': name,
            'age': age,
            'height': height,
        },
        'form': pd
        }

    else:
        print("Form is invalid")
        context = { 'form': pd }

    return render(request, "app1/my_form.html", context=context)

in der vorlage kann ich als {{e}} auf den erroe zugreifen


-3

Importieren Sie einfach IntegrityError

from django.db import IntegrityError

und benutze es in try / Except

try:
    //Do what is needed to be done
 except IntegrityError as e:
    //return what is supposed to be returned

Danke @Soren Ich habe gerade meine Antwort bearbeitet


Das sagt nicht, wie es geht.
Sören
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.