In Part 1 of this post, we create a form which conditionally shows a checkbox for user confirmation. The implementation is to raise an validation error when a condition is met. That does not work well with multiple confirmations, as the checking stops when the first condition is met. We need a way to check all conditions without raising an validation error, with one checkbox to confirm them all. We can do that with Form.add_error()
Instead of raising an validation error like in Part 1 of this post:
class InvoiceForm(forms.ModelForm): ... def clean(self): super().clean() ... if all((key in self.cleaned_data for key in ['date', 'confirm'])): if self.cleaned_data['date'].weekday() == 6 and not self.cleaned_data['confirm']: raise forms.ValidationError(MSG001)
We add an validation error when a condition is met:
class InvoiceForm(forms.ModelForm): ... def clean(self): super().clean() ... if 'confirm' in self.cleaned_data and not self.cleaned_data['confirm']: if 'date' in self.cleaned_data: d = self.cleaned_data['date'] if d.weekday() == 6: self.add_error(None, forms.ValidationError(CONFIRM_MSG[1])) if (datetime.date.today() - d).days > 14: self.add_error(None, forms.ValidationError(CONFIRM_MSG[2]))
In the example above, a confirmation is required if either the invoice date falls on a Sunday or the invoice date is more than 14 days in the past. CONFIRM_MSG is a dict of confirmation messages such as the following:
CONFIRM_MSG = { 1: "The invoice date does not fall on a Sunday. Please check confirm to proceed.", 2: "The invoice date is more than 14 days in the past. Please check confirm to proceed.", }
In the Form.__init__() method, we check for existence of any of the confirmation messages to show the checkbox. Note the use of the Form.non_field_errors() method to retrieve all non-field errors, such as those added in the Form.clean().
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) ... confirm_set = set(CONFIRM_MSG.values()) if confirm_set.intersection(self.non_field_errors()): self.fields['confirm'].widget = forms.CheckboxInput()
No comments:
Post a Comment