Django-Formulare: Wenn nicht gültig, Formular mit Fehlermeldung anzeigen

112

Bei Django-Formularen kann überprüft werden, ob das Formular gültig ist:

if form.is_valid(): 
    return HttpResponseRedirect('/thanks/')

Aber ich vermisse, was zu tun ist, wenn es nicht gültig ist? Wie kann ich das Formular mit den Fehlermeldungen zurücksenden? Ich sehe das "Sonst" in keinem der Beispiele.

user984003
quelle

Antworten:

241

Wenn Sie dieselbe Ansicht rendern, wenn das Formular ungültig ist, können Sie in der Vorlage mit auf die Formularfehler zugreifenform.errors .

{% if form.errors %}
    {% for field in form %}
        {% for error in field.errors %}
            <div class="alert alert-danger">
                <strong>{{ error|escape }}</strong>
            </div>
        {% endfor %}
    {% endfor %}
    {% for error in form.non_field_errors %}
        <div class="alert alert-danger">
            <strong>{{ error|escape }}</strong>
        </div>
    {% endfor %}
{% endif %}

Ein Beispiel:

def myView(request):
    form = myForm(request.POST or None, request.FILES or None)
    if request.method == 'POST':
        if form.is_valid():
            return HttpResponseRedirect('/thanks/')
    return render(request, 'my_template.html', {'form': form})
Aamir Adnan
quelle
Ich habe ein einfaches Beispiel hinzugefügt. Stellen Sie sicher, dass Sie den gleichen Ansatz verfolgen, den ich erwähnt habe.
Aamir Adnan
1
Aha. Ich gebe das gleiche Formular zurück, das ich erhalten habe. Die Fehlermeldungen wurden automatisch von der Funktion is_valid () hinzugefügt.
user984003
Ja, du hast es jetzt verstanden. Wenn Sie das Formular nicht manuell gerendert haben, werden die Fehler automatisch für jedes Feld angezeigt.
Aamir Adnan
@ AlexanderSupertramp myFormist eine Instanz von entweder forms.Formoder forms.ModelForm, lesen Sie über Django Forms
Aamir Adnan
Was ist, wenn ich keine Ansicht habe? ZB mit einem Standard-Administrationsformular im CMS. Zum Beispiel UNIQUE constraint failed:ausnahmsweise?
Geoidesic
19

views.py

from django.contrib import messages 

def view_name(request):
    if request.method == 'POST':
        form = form_class(request.POST)
        if form.is_valid():
            return HttpResponseRedirect('/thanks'/)
        else:
            messages.error(request, "Error")
return render(request, 'page.html', {'form':form_class()})

Wenn Sie die Fehler des Formulars anzeigen möchten, die nicht gültig sind, geben Sie einfach {{form.as_p}} wie unten beschrieben ein

page.html

<html>
    <head>
        <script>
            {% if messages %}
                {% for message in messages %}
                    alert(message);
                {% endfor %}
            {% endif %}
        </script>
    </head>
    <body>
        {{form.as_p}}
    </body>
</html> 
Catherine
quelle
Und was kehre ich dann zurück? Wie kommt das zu meiner Vorlage?
user984003
Ich aktualisiere meinen Code. Wenn Sie möchten, können Sie in Ihrer Vorlage auch eine for-Schleifennachricht anstelle eines Skripts einfügen.
Catherine
1
Dies ist ein cooler Ansatz - muss aber wachsam sein ('{{message}}');
Amchugh89
Wie würden Sie der Fehlermeldung aus der Ansicht etwas Beschreibenderes hinzufügen als "Fehler", wie Sie es getan haben messages.error(request, "Error")?
cbuch1800
3
def some_view(request):
    if request.method == 'POST':
        form = SomeForm(request.POST)
        if form.is_valid():
            return HttpResponseRedirect('/thanks'/)
    else:
        form = SomeForm()
    return render(request, 'some_form.html', {'form': form})
Lukasz Koziara
quelle
3

UPDATE: Eine detailliertere Beschreibung der Formset-Fehler wurde hinzugefügt.


Form.errors kombiniert alle Feld- und Nichtfeldfehler. Daher können Sie das HTML folgendermaßen vereinfachen:

Vorlage

    {% load form_tags %}

    {% if form.errors %}
    <div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert">
        <div id="form_errors">
            {% for key, value in form.errors.items %}
                <span class="fieldWrapper">
                    {{ key }}:{{ value }}
                </span>
            {% endfor %}
        </div>
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    {% endif %}


If you want to generalise it you can create a list_errors.html which you include in every form template. It handles form and formset errors:

    {% if form.errors %}
    <div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert">
        <div id="form_errors">

            {% for key, value in form.errors.items %}
                <span class="fieldWrapper">
                    {{ key }}:{{ value }}
                </span>
            {% endfor %}
        </div>
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    {% elif formset.total_error_count %}
    <div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert">
        <div id="form_errors">
            {% if formset.non_form_errors %}
                {{ formset.non_form_errors }}
            {% endif %}
            {% for form in formset.forms %}
                {% if form.errors %}
                    Form number {{ forloop.counter }}:
                    <ul class="errorlist">
                    {% for key, error in form.errors.items %}
                        <li>{{form.fields|get_label:key}}
                            <ul class="errorlist">
                                <li>{{error}}</li>
                            </ul>
                        </li>
                    {% endfor %}
                    </ul>
                {% endif %}
            {% endfor %}

        </div>
    </div>

    {% endif %}

form_tags.py

from django import template

register = template.Library()


def get_label(a_dict, key):
    return getattr(a_dict.get(key), 'label', 'No label')


register.filter("get_label", get_label)

Eine Einschränkung: Im Gegensatz zu Formularen enthält Formset.errors keine non_field_errors.

P. Maino
quelle
0

Sie können dies einfach so tun, da das Formular bei der Initialisierung auch Formulardaten und ungültige Daten enthält:

def some_func(request):
    form = MyForm(request.POST)
    if form.is_valid():
         //other stuff
    return render(request,template_name,{'form':form})

if löst den Fehler in der Vorlage aus, falls vorhanden, aber die Formulardaten bleiben weiterhin wie folgt:

error_demo_here

Dinesh Kc
quelle
-1

Sie können einfach eine Flag-Variable setzen, in diesem Fall is_successed .

def preorder_view(request, pk, template_name='preorders/preorder_form.html'):
    is_successed=0
    formset = PreorderHasProductsForm(request.POST)
    client= get_object_or_404(Client, pk=pk)
    if request.method=='POST':
        #populate the form with data from the request
       # formset = PreorderHasProductsForm(request.POST)
        if formset.is_valid():
            is_successed=1
            preorder_date=formset.cleaned_data['preorder_date']
            product=formset.cleaned_data['preorder_has_products']
            return render(request, template_name, {'preorder_date':preorder_date,'product':product,'is_successed':is_successed,'formset':formset})



    return render(request, template_name, {'object':client,'formset':formset})

Anschließend können Sie in Ihre Vorlage einfach den folgenden Code einfügen

{%if is_successed == 1 %}
<h1>{{preorder_date}}</h1>
<h2> {{product}}</h2>
{%endif %}
gtopal
quelle