4

I'm new to both django and python and currently trying to build a form with various options as well as an "other" option for options not on the list. I'd like to define the option such that when "other" is checked, the form only validates if the other text box contains a non-empty value.

Is there a proper way to extend django forms/fields/widgets to accomplish this? The closest thing could find after searching google and stackoverflow is this example which provides code to extend create a custom renderer, widget, and form field but it is based on an older version of django.

Dave
  • 6,141
  • 2
  • 38
  • 65

1 Answers1

4

If you're using django.forms.ModelForm to render your forms you can do this in the form validation for your options field (clean_[your field name]).

from django import forms

class YourModelForm(forms.ModelForm):
    def clean_your_options(self):
        your_options = self.cleaned_data.getlist('your_options')

        if 'other' in your_options:
            other_text_input = self.cleaned_data.get('other_text_input')
            if len(other_text_input) == 0:
                raise forms.ValidationError('Other text input must contain value')

        return your_options
mVChr
  • 49,587
  • 11
  • 107
  • 104
  • I'm just using plain old django.forms.Forms. Does your answer apply in that context? – Dave Jul 26 '12 at 14:39
  • Yes, it should work just fine: https://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-a-specific-field-attribute – mVChr Jul 26 '12 at 14:48
  • Thank's for the post! This looks much easier than what I was trying. I'll give it a shot later tonight. – Dave Jul 26 '12 at 14:50
  • 1
    Worked perfectly with one caveat. I had to externalize the cleaned_data into a variable and define it like `cleaned_data = super(ContactForm, self).clean()` The reason being that, since this is called during form validation, self.cleaned_data didn't contain all info I needed. – Dave Jul 27 '12 at 20:53
  • 1
    @Dave, I hit the same problem as you, but had another way to address it. Presumably you are putting `other_text_input` after `your_options`, which explains why `other_text_input` isn't available in `self.cleaned_data` by the time you get there. So my solution was to move this logic from `clean_your_options` to `clean_other_text_input`. However I was doing this on a single-select field, so I do not know for sure if it would apply for a multiple-choice one. – floer32 Oct 06 '12 at 15:24