1

This particular form has 2 boolean fields, if the first field is No/False, then the next two fields become required. This form does work, but it seems very ugly to me.

  1. Without clean_approved, approved is not actually required, meaning the required=True argument is just documentation, not working code
  2. The self._errors dict code MIGHT (not in this case) overwrite any other errors that were present in that field.

With all the other ways Django makes it easy to make beautiful code, I must be doing something wrong for this Boolean field (that should be required) and the optionally required fields based on the answer to the first field.

Please show me the right way to do this.

class JobApprovalForm(forms.Form):
    approved = forms.NullBooleanField(required=True)
    can_reapply = forms.NullBooleanField(required=False)
    reject_reason = forms.CharField(required=False, widget=forms.Textarea())


    def clean_approved(self):
        """ Without this, approved isn't really required! """
        if self.cleaned_data['approved'] == None:
            raise forms.ValidationError(_("This field is required."))
        return self.cleaned_data['approved']

    def clean(self):
        """ Make the other two fields required if approved == False """
        if not self._errors and self.cleaned_data['approved'] == False:
            required_msg = [_("If this job is not approved, this field is required")]

            if self.cleaned_data['can_reapply'] == None:
                self._errors['can_reapply'] = self.error_class(required_msg)
            if not self.cleaned_data['reject_reason']:
                self._errors['reject_reason'] = self.error_class(required_msg)
        return self.cleaned_data
boatcoder
  • 17,525
  • 18
  • 114
  • 178
  • I asked a question a few weeks ago about a declarative library to do this stuff. I think the answer is just that this is a whole in Django right now, not even plugged by a third party library. – Marcin May 19 '14 at 00:25

1 Answers1

0

While mit might seem a bit excessive you could consider using an inline form.

The outer Form contains your "approved" setting. the inline form handles your rejection objects.

This will allow you to separate two different concerns. First case: approval yes/no. Second case: rejection handling

Unfortunately I can't provide you with example code right now,

but please have a look at this SO Question to get an initial idea of this concept

Inline Form Validation in Django

Community
  • 1
  • 1
Dr.Elch
  • 2,105
  • 2
  • 17
  • 23
  • Well that would work in the admin, but I'm not sure how that is any cleaner than what I have at the moment. I don't think inlines are supported outside of the admin, you have formsets, but I can't see that would make this code any cleaner either. – boatcoder May 19 '14 at 17:11