Django Forms: se non valido, mostra il modulo con messaggio di errore


112

I moduli Django, può verificare se il modulo è valido:

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

Ma mi manca cosa fare se non è valido? Come restituisco il modulo con i messaggi di errore? Non vedo "altro" in nessuno degli esempi.

Risposte:


242

Se si esegue il rendering della stessa vista quando il modulo non è valido, nel modello è possibile accedere agli errori del modulo utilizzandoform.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 %}

Un esempio:

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})

Ho aggiunto un semplice esempio. Assicurati di seguire lo stesso approccio che ho menzionato.
Aamir Adnan

1
Vedo. Restituisco la stessa forma in cui sono entrato. I messaggi di errore sono stati aggiunti automaticamente dalla funzione is_valid ().
user984003

sì, hai capito adesso. Se non hai reso il modulo manualmente, gli errori verranno visualizzati automaticamente per ogni campo.
Aamir Adnan

@AlexanderSupertramp myFormè un'istanza di forms.Formo forms.ModelForm, leggi di Django Forms
Aamir Adnan

Cosa succede se non ho una vista ... ad esempio utilizzando un modulo di amministrazione standard all'interno del CMS. Ad esempio su UNIQUE constraint failed:un'eccezione?
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()})

Se vuoi mostrare gli errori del modulo diversi da quello non valido, metti {{form.as_p}} come quello che ho fatto di seguito

page.html

<html>
    <head>
        <script>
            {% if messages %}
                {% for message in messages %}
                    alert(message);
                {% endfor %}
            {% endif %}
        </script>
    </head>
    <body>
        {{form.as_p}}
    </body>
</html> 

E poi cosa restituisco? Come arriva questo al mio modello?
user984003

Aggiorno il mio codice Puoi anche inserire il messaggio per loop nel tuo modello invece nello script, se lo desideri.
catherine

1
questo è un approccio interessante, ma deve essere attento ('{{message}}');
amchugh89

Come inseriresti qualcosa di più descrittivo nel messaggio di errore dalla vista rispetto a "Errore" come hai fatto 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})

3

AGGIORNAMENTO: aggiunta una descrizione più dettagliata degli errori del formset.


Form.errors combina tutti i field e non_field_errors. Quindi puoi semplificare l'html in questo modo:

modello

    {% 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)

Un avvertimento: a differenza dei form Formset.errors non include non_field_errors.


0

semplicemente puoi fare così perché quando hai inizializzato il modulo in contiene dati del modulo e anche dati non validi:

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

if solleverà l'errore nel modello se ne ha, ma i dati del modulo rimarranno come:

error_demo_here


-1

Puoi mettere semplicemente una variabile flag, in questo caso 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})

successivamente nel tuo modello puoi semplicemente inserire il codice qui sotto

{%if is_successed == 1 %}
<h1>{{preorder_date}}</h1>
<h2> {{product}}</h2>
{%endif %}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.