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