pythondjangopython-3.xformsdjango-formwizard

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

Solution

  • 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.