Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional Form Field in Django wizard form

I am using wizard forms in django. I want to create a form field only if answer to some other form field is marked "yes" otherwise I don't want this new form field. How can I do this ?
I have tried some other answers related to this but most of them tells about how to mark field required or not but I want to display that field only if answer to other field is "Yes"

Django Form Wizard with Conditional Questions

In below code I want to display field "Pool2" only if answer to field "Pool" is marked "yes" otherwise I don't want that field. Basically I want to get some details of pool in field "Pool2" if there is pool in user's house.

forms.py

class ListingForm2(forms.Form):
     Pool = (
        ("Yes","Yes"),
        ("No","No"),
    )
    Pool = forms.ChoiceField(choices = Pool,label = "Does your property have a pool ?")
    Pool2 = forms.CharField(required=False)

Views.py

class ListingWizard(SessionWizardView):
    template_name = 'listing_form.html'
    form_list = [ListingForm1,ListingForm2,ListingForm3,ListingForm4]
    def done(self, form_list, **kwargs):
        save_data(form.cleaned_data for form in form_list)
        return render(self.request,'done.html',{
            'form_data' : [form.cleaned_data for form in form_list],
            })
like image 391
Kanish Anand Avatar asked Jul 13 '19 14:07

Kanish Anand


People also ask

What is form Is_valid () in Django?

The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class. It returns True if data is valid and place all data into a cleaned_data attribute.

What is forms ModelForm in Django?

Django Model Form It is a class which is used to create an HTML form by using the Model. It is an efficient way to create a form without writing HTML code. Django automatically does it for us to reduce the application development time.

What is form cleaned_data in Django?

cleaned_data returns a dictionary of validated form input fields and their values, where string primary keys are returned as objects. form. data returns a dictionary of un-validated form input fields and their values in string format (i.e. not objects).

How do you make a field non editable in Django?

Every field comes in with built-in validations from Django validators. One can also add more built-in field validations for applying or removing certain constraints on a particular field. editable=False will make the field disappear from all forms including admin and ModelForm i.e., it can not be edited using any form.


1 Answers

What you are trying to do have to be done with JavaScript, you could do it with only Django posts but it is not a right way.

Check this out:

class BookForm(forms.ModelForm):
    has_sequel = forms.BooleanField(initial=True)

    class Meta:
        model = Book
        fields = ['author', 'length', 'has_sequel', 'sequel']

    class Media:
        js = ('book_form.js', )

    def clean(self):
        if self.cleaned_data['has_sequel'] and self.cleaned_data['sequel'] is None:
            raise ValidationError('You should indicate the sequel if the book has one.')


class BookView(FormView):
    template_name = 'book_form.html'
    form_class = BookForm
    success_url = '/done/'

This code is including a Javascript with the form, this way you could reuse the form with its own Javascript, the Javascript code should be something like this (you maybe have to change javascript depending on how you print your form in the template):

$(document).ready(function() {
    $('#id_has_sequel')[0].addEventListener('change', (event) => {
        let sequelField = $('#id_sequel').parents('p');
        if (event.target.checked) {
            sequelField.show();
        } else {
            sequelField.hide();
        }
    })
});

And the template should be something like this:

{% load static %}

<head>
    <title>Book form</title>

    <script src="{% static 'jquery-3.4.1.min.js' %}"></script>
    {{ form.media }}
</head>

<form method="post">{% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Send message">
</form>

If you have any question feel free to ask but trying to do this without Javascript it is not a good approach. As much you will find some kind of Django widget that will use Javascript too.

like image 80
Hagyn Avatar answered Sep 30 '22 05:09

Hagyn