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?

Rajat Saxena
quelle

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 .

Joe
quelle
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.

Chirael
quelle
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).

bruno desthuilliers
quelle
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

Krzysiek Hans
quelle
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

Luke Marak
quelle
-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

Ahmed Adewale
quelle
Das sagt nicht, wie es geht.
Sören