John Mee
John Mee

Reputation: 52343

How to make some django form fields depend on the value of other fields?

I have a form that requires some fields only if a radio button is selected.

If i set the field as "required=True" then it behaves has desired, but how do I get it to behave as "required=False" when the radio button is not selected?

I'm thinking I'd go for a default of required=False then check the value of the radio button in form.clean() and call for a clean_<field> for those fields that are now required, but it doesn't seem to be that simple. Or is it?

Alternatively I'd start with required=True, then in form.clean() check the value of the radio button, and if not set then just remove any errors raised from the no-longer-required fields?

Upvotes: 1

Views: 3128

Answers (2)

John Mee
John Mee

Reputation: 52343

Oh, looky, I worked it out all by my lonesome... the latter option is indeed much simpler than trying to find and call validation routines on specific fields. Much easier to squash the errors:

Set all the potentially required fields as required=True then in form.clean() test the value of the other field and, if necessary, just delete the errors from self.errors

# payment type
payment_method = forms.CharField(max_length="20", required=True)
payment_method.widget=forms.RadioSelect(choices=PAYMENT_METHOD_CHOICES)

# credit card details
cc_number = CreditCardField(max_length=20, required=True)
cc_name = forms.CharField(max_length=30, required=True)
cc_expiry = ExpiryDateField(required=True)
cc_ccv = VerificationValueField(required=True)

def clean(self):
    data = super(PaymentForm, self).clean()
    if data.get('payment_method') == 'paypal':
        for field_name in ['cc_number','cc_name','cc_expiry','cc_ccv']:
            if field_name in self.errors:
                del self.errors[field_name]

Upvotes: 2

Peter DeGlopper
Peter DeGlopper

Reputation: 37364

form.clean is the right place to do this. What's not right is calling clean_<field> for other fields - they will have already been cleaned and their values will be in the cleaned_data dict.

Take a look at the example in the docs: https://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other It runs through almost exactly this scenario, showing how you can test one field based on another and how you can either raise a form-level error when missing or bind the error to one of the fields.

Upvotes: 1

Related Questions