Bentuk Django: jika tidak valid, tampilkan formulir dengan pesan kesalahan

112

I Django bentuk, itu dapat memeriksa apakah formulir itu valid:

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

Tapi saya kehilangan apa yang harus dilakukan jika tidak valid? Bagaimana cara mengembalikan formulir dengan pesan kesalahan? Saya tidak melihat "lain" di salah satu contoh.

pengguna984003
sumber

Jawaban:

242

Jika Anda membuat tampilan yang sama ketika formulir tidak valid maka di Templat Anda dapat mengakses kesalahan formulir menggunakanform.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 %}

Sebuah contoh:

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
sumber
Saya telah menambahkan contoh sederhana. Pastikan Anda mengikuti pendekatan yang sama yang telah saya sebutkan.
Aamir Adnan
1
Saya melihat. Saya mengembalikan formulir yang sama dengan yang saya dapatkan. Pesan kesalahan secara otomatis ditambahkan ke dalamnya oleh fungsi is_valid ().
pengguna984003
ya, Anda mengerti sekarang. Jika Anda belum membuat formulir secara manual maka kesalahan akan otomatis ditampilkan untuk setiap bidang.
Aamir Adnan
@AlexanderSupertramp myFormadalah turunan dari salah satu forms.Formatau forms.ModelForm, baca tentang Formulir Django
Aamir Adnan
Bagaimana jika saya tidak memiliki tampilan .. misalnya menggunakan formulir admin standar dalam CMS. Misalnya tentang UNIQUE constraint failed:pengecualian?
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()})

Jika ingin menampilkan kesalahan formulir selain yang tidak valid cukup letakkan {{form.as_p}} seperti yang saya lakukan di bawah ini

page.html

<html>
    <head>
        <script>
            {% if messages %}
                {% for message in messages %}
                    alert(message);
                {% endfor %}
            {% endif %}
        </script>
    </head>
    <body>
        {{form.as_p}}
    </body>
</html> 
catherine
sumber
Lalu apa yang harus saya kembalikan? Bagaimana ini bisa sampai ke template saya?
pengguna984003
Saya memperbarui kode saya. Anda juga dapat meletakkan for loop message di template Anda sebagai gantinya dalam skrip, jika Anda mau.
Catherine
1
ini adalah pendekatan yang keren - tetapi perlu waspada ('{{message}}');
amchugh89
Bagaimana Anda menempatkan sesuatu yang lebih deskriptif dalam pesan kesalahan dari tampilan daripada 'Kesalahan' seperti yang telah Anda lakukan 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
sumber
3

UPDATE: Menambahkan deskripsi yang lebih mendetail tentang kesalahan formset.


Form.errors menggabungkan semua field dan non_field_errors. Oleh karena itu Anda dapat menyederhanakan html menjadi ini:

template

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

Satu peringatan: Berbeda dengan form, Formset.errors tidak menyertakan non_field_errors.

P. Maino
sumber
0

Anda bisa melakukan seperti ini karena ketika Anda menginisialisasi formulir di berisi data formulir dan data tidak valid juga:

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

jika akan memunculkan kesalahan di templat jika ada tetapi data formulir akan tetap seperti:

error_demo_di sini

Dinesh Kc
sumber
-1

Anda dapat menempatkan variabel flag, dalam hal ini berhasil .

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

setelah itu di template Anda, Anda tinggal memasukkan kode di bawah ini

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